虚拟机锁优化

  • 锁偏向

  synchronized默认采取非公平锁,锁偏向是指线程在释放锁后再次进入请求队列中等待获取锁时,虚拟机会优先唤醒该线程。并省去获取锁的操作,进行无锁操作。

  代码:

public class BIasLockTest {
    public static void main(String[] args) {
        Object lock = new Object();
        AtomicInteger num = new AtomicInteger();
        for(int i = 0; i < 100; i++){
            Thread t = new ThreadA("t" + i,lock,num);
            t.start();
        }
    }
}
class ThreadA extends Thread{
    private Object lock;
    private AtomicInteger num;

    public ThreadA(String name, Object lock,AtomicInteger num) {
        super(name);
        this.lock = lock;
        this.num = num;
    }

    @Override
    public void run() {
        while(num.getAndIncrement() < 100){
            synchronized (lock){
                System.out.print(Thread.currentThread().getName() + "  ");
            }
        }
    }
}

 输出片段:

 t0  t0  t0  t0  t0  t0  t0  t0  t0  t0  t0  t0  t0  t0  t0  t4  t4  t4  t4  t4  t4  t4  t4  t4  t4  t3  t3  t3  t3  t3  t3  t3  t3  t3  t3  t3  t3
t3  t3  t4  t4  t4  t4  t0  t55  t2  t44  t1  t8  t7  t3

  

  • 轻量级锁

  当锁竞争比较激烈,偏向锁就会失效,例如这一段:t4 t4 t4 t0 t55 t2 t44 t1 t8 t7 t3

  基本上每次获取锁的线程都不一样,偏向锁失效后,会升级为轻量级锁。

  轻量级锁将对象头部作为指针指向持有锁的线程堆栈的内部,来判断一个线程是否持有对象锁。

  线程获取轻量级锁成功后可以进入临界区。获取失败则膨胀为重量级锁。

  • 自旋锁

  轻量级锁膨胀为重量级锁后,为了避免线程真实的在操作系统层面挂起,虚拟机让线程执行几个空循环,目的是等待其他线程释放锁资源。

  空循环以后,如果获取锁成功,则自旋成功,如果依旧获取失败,则线程在操作系统层面挂起,等待被唤醒。

  • 锁消除

  锁消除涉及逃逸分析,逃逸分析是观察某一个变量是否会逃出某一个作用域。

  例如在方法中存在一个Vector类型的临时变量,这个临时变量只在这个方法中使用,那个对这个临时变量的任何操作都只会在当前线程进行。这类无意义的加锁完全可以去掉。

参考:

《实战Java高并发程序设计》

猜你喜欢

转载自www.cnblogs.com/simple-ly/p/11123650.html