synchronized底层实现

01/26 17:19
阅读数 36

 1、锁升级的过程

  当多个线程同时竞争一个对象监视器时:当前对象结构中的mark word中是否是当前线程id,如果是则当前线程获得偏向锁

如果不是,则通过CAS将当前线程id置换到mark word中,如果成功则获得偏向锁,如果不成功则说明有竞争,升级为轻量级锁。

后续再通过CAS将线程的指针放到mark word中,若成功则获得锁,否则升级为自旋锁。自旋锁仍然为轻量级锁,不成功升级为重量级锁。

 

  对象结构:在JVM中,对象在内存中的布局分为三块区域:对象头、实例数据和对齐填充

 

 

 mark word:存在于对象头中,存储对象的hashcode,锁标识,分代年龄及GC标识等信息

 

 

 由上图可以看出,为何偏向锁是将线程id放入mark word,轻量级锁为何将锁的指针放入mark word。

 

偏向锁:指偏向于第一个访问的线程,在运行过程中,同步锁没有竞争,则会在这个线程的头部加一个标志位,标记为偏向锁,如果发生竞争则会升级为轻量级锁或者重量级锁

 

自旋锁:线程请求不到对象锁时不会堵塞,只是自己循环一下等待对象锁的释放。因为线程的堵塞和唤醒非常消耗内存,所以自旋锁可以很好的优化这个问题。

但它只适合等待时间比较短的,而且并发量不高的场景。

 

2、升级到重量级锁后,如何运行

 

 

 当多线程竞争时,不满足的条件的线程会进入同步队列,满足条件后进入同步代码。在同步代码中执行wait方法,释放对象锁,进入右侧等待队列,当唤醒时 还需要再次获得互斥锁。

 

synchronized结构:

  Contention List:竞争队列,所有请求锁的线程首先被放在这个竞争队列中;

  Entry List:Contention List中那些有资格成为候选资源的线程被移动到Entry List中;

   Wait Set:哪些调用wait方法被阻塞的线程被放置在这里;

   OnDeck:任意时刻,最多只有一个线程正在竞争锁资源,该线程被成为OnDeck;

  Owner:当前已经获取到所资源的线程被称为Owner;

  大量并发线程会在contention List中,然后将有资格成为候选的放到entry list中。调用的wait的线程放到wait set中,当被唤醒后会放到entry list中。

指定EntryList中的某个线程为OnDeck线程(一般是最先进去的那个线程),然后onedeck线程去竞争锁,但是此时其他未进入contention list的线程会先自旋一下看是否能获得到锁,

所以说synchronied不是公平的。

 当使用synchronized加类锁时,会有严重的效率问题,此时需要考虑是否可以修改为细粒度锁,当修改细粒度锁时,要避免死锁。

 

上述若有不对,麻烦各位指正

 

原文出处:https://www.cnblogs.com/volare/p/12234466.html

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部