synchronized底层实现

 一、锁升级的过程

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

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

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

 

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

 

 

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

 

 

 由上图能够看出,为什么偏向锁是将线程id放入mark word,轻量级锁为什么将锁的指针放入mark word。线程

 

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

 

自旋锁:线程请求不到对象锁时不会堵塞,只是本身循环一下等待对象锁的释放。由于线程的堵塞和唤醒很是消耗内存,因此自旋锁能够很好的优化这个问题。code

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

 

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

 

 

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

 

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加类锁时,会有严重的效率问题,此时须要考虑是否能够修改成细粒度锁,当修改细粒度锁时,要避免死锁。

 

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

相关文章
相关标签/搜索