Java的synchronized锁优化过程总结

  一开始synchronized锁的实现是基于操作系统的提供的信号量(PV操作)实现的,这个就叫重量级锁这个实现默认一定存在数据竞争,不管有没有数据竞争都枷锁,所以是一种悲观的线程安全实现方法。所有最大的问题就是性能问题,会有用户态到核心态转换等一系列比较消耗资源的操作。

  所以JDK6是专门做了优化,最常用的优化措施是不断地重试,比较消耗CPU,这个就叫自旋锁

  自旋锁比较消耗CPU所以又做了一些优化,JDK 6中对自旋锁的优化,引入了自适应的自旋。而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定的。有了自适应自旋,随着程序运行时间的增长及性能监控信息的不断完善,虚拟机对程序锁的状况预测就会越来越精准,虚拟机就会变得越来越“聪明”了。

  随着硬件指令集的发展,有了另一种更加优化的操作,就是在硬件层面实现一条能够保证多次内存操作的原子性的指令,例如:测试并设置(Test-and-Set)、获取并增加(Fetch-and-Increment)、交换(Swap)、比较并交换(Compare-and-Swap,下文称CAS)和加载链接/条件储存(Load-Linked/Store-Conditional,下文称LL/SC)。这样就能更加精确地控制互斥,在CPU底层执行指令时判断数据是否冲突,相当于把加锁的范围缩小了。依赖于这种CAS指令的锁就叫做轻量级锁

  轻量级锁涉及CAS操作,进一步优化就是去掉这一CAS操作,默认都是同一线程操作数据,这个就叫做偏向锁,意思是偏向第一个获得它的线程,偏向锁的实现和轻量级锁原理都差不多,都是修改线程栈中数据,只是修改的数据不一样。一旦出现另外一个线程去尝试获取这个锁的情况,偏向模式就马上宣告结束,转化为轻量级锁。

  实际运行时,synchronized锁升级就是偏向锁 轻量级锁 自旋锁 重量级锁 这么个过程。

  参考:《深入理解Java虚拟机》

posted @ 2022-11-10 17:19  road2master  阅读(104)  评论(0编辑  收藏  举报