摘要:本文主要学习了多线程中有关锁的一些特性。
环境
Windows 10 企业版 LTSC 21H2
Java 1.8
1 锁升级
在JDK1.5之前,使用synchronized是操作系统级别的重量级操作。在JDK1.6之后,为了减少获得锁和释放锁所带来的性能消耗,引入了轻量级锁和偏向锁。
在Java对象头里的MarkWord中存储了synchronized用到的锁,锁升级主要依赖占用1位的偏向锁标志位和占用2位的锁标志位。
1.1 无锁
对象被实例化后,如果没有线程竞争锁,就是无锁状态。
偏向锁标志位为0,锁标志位为01。
1.2 偏向锁
同步代码一直被同一个线程访问,在后续访问时会自动获得偏向锁。
偏向锁标志位为1,锁标志位为01。
1.3 轻量锁
同步代码存在线程竞争,会升级为轻量锁,通过CAS自旋尝试获取锁。
偏向锁标志位为0,锁标志位为00。
1.4 重量锁
同步代码存在线程竞争,并且通过CAS自旋尝试超过一定次数以后,仍未能获取锁,会升级为重量锁。
偏向锁标志位为0,锁标志位为10。
2 锁消除
如果在同步代码块中锁的是局部对象,而不是共享对象,编译器就会无视同步代码块,相当于并没有对锁住的对象加锁,消除了锁的使用。
3 锁粗化
如果前后同步代码块锁住的都是同一个对象,编译器就会把代码块合并成更大的代码块,加粗加大范围,一次申请锁使用即可,避免多次的申请和释放锁,提升了性能。
条