<JavaEE> 锁进阶 -- synchronized 的锁优化
2023-12-15 13:10:33
目录
一、如何形容 synchronized 锁
synchronized 锁是一个内部优化非常好的锁,大部分情况下这个锁都是适用的。 |
在初始阶段 synchronized 是一个乐观锁、轻量级锁、自旋锁,随着锁冲突变得更激烈,synchronized 会转换为悲观锁、重量级锁、挂起等待锁。 |
与此同时,synchronized 还是一个可重入锁、非公平锁、非读写锁。 |
二、锁升级
synchronized 的加锁过程 | |||
无锁 | 偏向锁 | 轻量级锁 | 重量级锁 |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> | |||
JVM 将 synchronized 锁分为 以上四个阶段,会根据实际情况,对锁进行升级。应该注意的是,目前所只能升级,不能降级。 |
2.1 偏向锁
阶段描述: |
当锁第一次被一个线程获取时,优先进入偏向锁状态。 |
偏向锁并非真的“加锁”,而是在对象头中做一个“偏向锁标记”,记录该锁属于哪个线程。 |
如果后续没有其他线程竞争该锁,那么该锁不会有后续升级操作,减少了加锁带来的系统开销。 |
如果后续有其他线程竞争该锁,那么锁会真正的加锁,升级为轻量级锁。由于之前已经记录了该锁属于哪个线程,所以此时锁也是被记录的线程获取的。 |
这种升级操作实际上属于延迟加锁,不必要不加锁,减少了加锁的系统开销,提高了运行效率。 |
2.2 轻量级锁
阶段描述: |
随着锁竞争的开始,锁将进入轻量级锁的状态,在初始状态是通过自旋锁实现的。 |
自旋锁是循环不断地让线程尝试获取锁。优点在于当锁被释放,其他线程可以第一时间获取到锁。 |
而自旋锁的缺点也在于会一直占用CPU资源。synchronized 对此也进行了优化,当自旋达到一定的时间或次数时,就不再自旋了,将转换为挂起等待。 |
同时,synchronized 内部也会统计当前锁对象有多少线程在竞争,如果锁竞争更加激烈,synchronized 就会从轻量级锁升级为重量级锁。 |
2.3 重量级锁
阶段描述: |
重量级锁是指使用内核提供的 mutex 锁。 |
mutex 锁执行加锁操作时,会先进入内核态,在内核态判定当前锁是否已经被占用。 |
如果该锁没有被占用,则加锁成功,并切换回用户态。 |
如果该锁已经被占用,则加锁失败,线程阻塞等待,直到下一次唤醒。 |
三、锁消除
什么是锁消除? |
锁消除是?synchronized 锁的一种较保守的优化策略,通过编译器和JVM判断锁是否可以消除。 |
这里的锁消除只会处理一些直接可以判断,完全不涉及线程安全问题的锁,比如在单线程环境下使用 StringBuffer 类中的方法。 |
四、锁粗化
什么是锁粗化? |
这里有一个锁的粒度的概念,可以这么认为:在锁对象代码块中的代码越少则认为锁的粒度越细,反之则是越粗。 |
实际开发中,使用细粒度的锁,往往是为了锁可以被其他线程及时获取。但有时,可能很长一段时间都没用其他线程来竞争这个锁。 |
因此,如果一段逻辑中出现多次加锁解锁,根据编译器和JVM的判断会自动对锁进行粗化。 |
锁粗化是指将多个细粒度的锁合并为一个粗粒度的锁,可以在特定场景下提高程序的执行效率,减小系统开销。 |
阅读指针 -> 《CAS编程及相关类》
链接生成中..........
文章来源:https://blog.csdn.net/zzy734437202/article/details/134933938
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!