多线程之synchronized关键字

多个线程对同一片存储空间进行访问,这时存储空间里面的数据叫做共享数据。线程并发进行写操作时,共享数据就可能产生安全性问题,解决这个问题除了我们前面介绍的一些类外,jdk也提供了一个关键字synchronized保证共享数据的原子性。

用法

例子依然可以在 github
下载

  • 修饰静态方法:类级别同步
  • 修饰成员方法:对象级别的同步
  • 方法块中使用:对给定对象加锁,同步代码

原理

  • java 程序层级:synchronized(o)
  • 字节码层级:monitorenter moniterexit (字节码文件中可以看到)
  • jvm最底层: 使用lock comxchg …..指令 (保证原子性)

synchronized优化

synchronized在jdk1.6之前的版本中,因为是重量级锁(需要内核的调度),效率上有很大问题,所以jdk1.6对synchronized的加锁过程做了一些优化,加锁有了升级的过程,不再是上来就加重量级锁。

无锁 -> 偏向锁 -> 轻量级锁(自旋锁)-> 重量级锁

  • 无锁:JVM启动的4秒内,偏向锁没有打开,那时普通对象是无锁
  • 偏向锁: markword 上记录当前线程指针,下次同一个线程加锁的时候,不需要争用,只需要判断线程指针是否同一个,所以偏向加锁的第一个线程。hashCode备份在线程栈上。
  • 轻量级锁: 有争用时,锁升级为轻量级锁,每个线程有自己的LockRecord在自己的线程栈上,用CAS去争用markword的LR的指针,指针指向哪个线程的LR,哪个线程就拥有锁
  • 重量级锁:当jvm觉得冲突比较大,CAS自旋浪费cpu时,升级为重量级锁。

还有一些其他的优化。

  • 锁消除:当jvm检测上下文,发现不存在多线程竞争时,进行锁消除。如:方法内部使用StringBuffer类(我们知道这里类的方法时加了synchronized的)
  • 锁粗化:当jvm检测到在一个while等循环里面使用了synchronized时,多次进行加锁的判断和检查浪费时间,那就直接放大到while外层吧,这就是锁粗化。如:while循环中使用StringBuffer类。

原文 

https://juejin.im/post/5ef30d2c6fb9a07e594ef46f

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » 多线程之synchronized关键字

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址