【并发】锁的升级

来源:互联网 发布:二元自动交易软件 编辑:程序博客网 时间:2024/06/11 03:52

       尽最大的可能提高程序的执行效率是所有的开发人员不断追求的目标之一。今天我们就来介绍javaSE的作者是如何减少获得锁和释放锁带来的性能消耗的。为了减少锁的性能消耗,javaSE1.6引入了“偏向锁”和轻量级锁。至此锁一共存在四种状态:无锁、偏向锁、轻量级锁、重量级锁。这几个状态会随着竞争情况逐渐升级。锁可以升级但不能降级,意味着偏向锁升级成轻量级锁后不能降级成偏向锁。这种锁升级却不能降级的策略,目的是为了提高获得锁和释放锁的效率。

 

偏向锁

         偏向锁,顾名思义,它会偏向于第一个访问锁的线程,如果在接下来的运行过程中,该锁没有被其他的线程访问,则持有偏向锁的线程将永远不需要触发同步。

         如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会尝试消除它身上的偏向锁,将锁恢复到标准的轻量级锁。(偏向锁只能在单线程下起作用)偏向锁可以提高带有同步但无竞争的程序性能。 它同样是一个带有效益权衡(TradeOff)性质的优化,也就是说,它并不一定总是对程序运行有利,如果程序中大多数的锁总是被多个不同的线程访问,那偏向模式就是多余的。在具体问题具体分析的前提下,有时候使用参数-XX:-UseBiasedLocking来禁止偏向锁优化反而可以提升性能。



轻量级锁

       线程在执行同步块之前,JVM会先在当前线程的栈桢中创建用于存储锁记录的空间,并将对象头中的Mark Word复制到锁记录中,官方称为Displaced Mark Word。然后线程尝试使用CAS将对象头中的Mark Word替换为指向锁记录的指针。如果成功,当前线程获得锁,如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁。如果在自旋锁加锁失败则升级为重量级锁。

       轻量级解锁时,会使用原子的CAS操作将DisplacedMark Word替换回到对象头,如果成功,则表示没有竞争发生。如果替换失败,说明有其他线程尝试过获取该锁,那就要在释放锁的同时,唤醒被挂起的线程。

 

自旋锁

         自旋锁并不是锁四种状态的一种,但是它也是提高性能的一种方式。当竞争存在时,如果线程可以很快就得到锁,那么就可以不再OS层挂起线程(这样很消耗性能),而让线程做几个空操作(自旋),如果在自旋的过程中得到锁便执行,无法得到便进入阻塞状态。

总结

        偏向锁、轻量级、重量级锁分别解决了三个问题,只有一个线程进入临界区则使用偏向锁,多个线程交替进入临界区则使用轻量级锁,多线程同时进入临界区就要使用重量级锁

0 0