java并发编程(七)synchronized原理之重量级锁 一、何为锁膨胀? 二、自适应自旋锁

前文讲解轻量级锁时,当线程使用CAS尝试对对象加锁,有两种失败情况,一种情况是自己执行了synchronized锁重入;另外一种,就是本文需要学习的重点内容:锁膨胀

一、何为锁膨胀?

轻量级锁是指在满足一定的条件内,使用CAS(自旋)来尝试获取对象锁的一种机制,如果超过以下条件,则会膨胀为重量级锁:

1)在jdk1.6前,默认10次,可通过-XX:PreBlockSpin来修改,或者自旋线程数超过CPU核数的一半。

2)jdk1.6之后,引入了自适应自旋锁,次数并非一成不变。根据获取锁的成功率来决定是否能有更长的等待时间。

假设当前Object对象,已经被Thread1所持有,当Thread2前来竞争这把锁,满足上述条件后,会发生锁膨胀,如下图所示:

如上所示,此时Thread2来获取轻量级锁肯定失败的,所以会进入锁膨胀的流程:

1)为Object对象申请Monitor锁,Object的Mark Word指向Monitor地址;Monitor的Owner指向Thread1的锁记录。

2)Thread2进入Monitor的EntryList当中,状态变成BLOCKED。

当Thread1执行完代码块的内容后,开始释放锁,使用CAS去重置Object的Mark Word,此时会失败。因为当前对象头存储的是Monitor的地址。

所示此时会进入重量级锁的解锁过程。将Monitor的Owner设置为null,同时唤醒EntryList中的Thread-2。

二、自适应自旋锁

jdk1.6之后,引入了自适应自旋锁,在重量级锁当中,也进行了一些优化。

前面提到当发生锁膨胀后,没持有锁的线程会进入Monitor的EntryList当中进行阻塞,实际情况是,会通过自适应自旋锁进行一定次数的自旋,如果获取到锁了,就避免进入阻塞状态(会进行上下文切换)。如果没获取到锁,此时在进入阻塞状态。

  • 自旋是占用CPU的,只有在多核CPU中才能发挥优势。
  • 自适应自旋锁会动态调整自旋次数,获取锁成功的次数多,就会多自旋几次;如果一次都没有成功,则会可能会直接进行阻塞。
  • java7后不能控制是否开启自旋锁。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章