JVM之锁与并发
JVM之锁与并发
扬花落尽丶 发表于9个月前
JVM之锁与并发
  • 发表于 9个月前
  • 阅读 26
  • 收藏 3
  • 点赞 0
  • 评论 0

移动开发云端新模式探索实践 >>>   

什么是锁:

  锁是多线程软件开发的必要工具之一,它的基本作用是保护临界区资源不会被多个线程同时访问收到破坏,由于多个线程访问造成对象的数据不一致,那么系统运行将会得到错误的结果。通过锁,可以让多个线程排队,一个一个进入临界区访问目标对象,使目标对象的状态总是保持一致,这就是锁存在的价值。  

对象头和锁:

   每个对象都有一个对象头,用于保护对象的系统信息。对象头中有一个成为Mark Word的部分,它是实现锁的关键。Mark Word在32位系统为一个32位的数据,64位系统为一个64位的数据。用来存放对象的哈希值、对象年龄、锁的指针等信息。

 32位系统距离Mark Word

   Mark Word中前25bit表示对象的哈希值,4位比特表示对象的年龄,1位比特表示是否为偏向锁,2位表示锁的信息。

  是否为偏向锁 锁的信息
无锁状态 0 01
偏向锁 1 01
轻量级锁 0 00
重量级锁 0 10

轻量级锁和重量级锁可以从Mark Word的后两位看出,然而无锁状态和偏量锁需要根据倒数第三个数据进行判断。

  •  偏向锁:

偏向锁是JDK1.6提出的一种锁优化方式。其核心思想是,如果程序没有竞争,则取消之前已经取得锁的线程同步操作。也就是说,若某一锁被线程获取后,便进入偏向锁模式,当线程再次请求的时候进行了锁请求,则锁退出偏向模式。在JVM中使用-XX:+UseBiasedLocking可以设置启动偏向锁。

  (当使用代码测试时,需要使用参数-XX:BiasedLockingStartupDelay表示虚拟机在启动后,立即启动偏向锁。如果不设置参数,虚拟机会默认在启动4秒后,才启动偏向锁)

应用场景:偏向锁在少量竞争的情况下,对系统性能有一定的帮助。但是在锁竞争激烈的场合下没有太强的优化效果,因为大量的竞争会导致持有锁的线程不停的切换,锁也很难保持在偏向模式。此时,使用锁偏向不仅得不到性能的优化,反而有可能降低系统的性能。因此,在激烈竞争的场合,可以尝试使用-XX:-UseBiasedLocking参数禁用偏向锁。

  • 轻量级锁:

如果偏向锁失败,Java虚拟机会让线程申请轻量级锁。轻量级锁在虚拟机内部,使用一个称为BasicObjectLock对象在线程栈中,因此该指针必然指向持有该锁的线程空间。当需要判断某一线程是否持有该对象锁时,也只需简单的判断对象头的指针是否在当前线程的栈地址范围内即可。同时,BasicLock对象的displaced_header字段,备份了援对象的Mark Word内容。BasicObjectLock对象的obj字段则指向该对象。

首先,BasicLock通过set_displaced_head()方法备份了援对象的Mark Word。接着,使用CAS操作,尝试BasicLock的地址复制到对象头的Mark Word。如果复制成功,那么加锁成功,否则认为加锁失败,那么轻量级锁就有可能被膨胀为重量级锁。

  • 锁膨胀:

当轻量级失败,虚拟机就会使用重量级锁。

第一步是废弃前面的BasicLock备份的对象头信息。第二步则正式启动重量级锁。启动过程分为两部:首先通过inflate()方法进行锁膨胀,其目的是获得对象的ObjectMonitor;然后使用enter()尝试进入该锁。

在enter方法调用中,线程很可能会在操作系统层面被挂起。如果这样,线程间切换和调度的成本就会比较高。

  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 4
博文 38
码字总数 31280
×
扬花落尽丶
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: