Synchronized的实现原理与应用。

2018-07-16  本文已影响0人  西瓜真好吃丶

在javaSE1.6中对Synchronized进行了大量的优化,使一个笨重的锁变得灵活了起来。
在讲Synchronized之前,要先介绍一下java的对象头:

从上面可以看出,共同点是都有3个bit给锁使用。
得出结论:java中的每一个对象都可以作为锁。

Synchronized的三种用法:

在javaSE1.6中锁一共有4种状态:无锁、偏向锁、轻量级锁、重量级锁。
下面把锁转换的流程说一遍:
当一个线程访问同步代码块并获取锁的时候,会在对象头和栈帧中的锁记录里存储锁偏向的线程ID。当该线程再次进入同步代码块时,只需判断对象头的Mark World里是否存储着指向当前线程的偏向锁。
  如果成功,则表示已获得了锁,直接进入。
  如果失败,则再判断该mark world中的锁标识是否为偏向锁。
     如果该锁标识为偏向锁则进行偏向锁的竞争。
     如果该锁标识不为偏向锁,则进行对应锁的竞争。

偏向锁的竞争及升级过程:
  1.线程2来竞争锁对象
  2.判断拥有偏向锁的线程1是否还存在
  3.如果线程1不存在,则设置偏向锁标识为0
  4.用cas操作替换锁线程ID为线程2,锁不升级,仍然为偏向锁。
  5.线程1仍然存在,暂停线程1;
  6.设置锁的标志位为00,偏向锁标识为0,升级为轻量级锁。
  7.在线程1的栈帧中创建用于存储锁记录的空间,并将对象头中的MarkWorld复制到锁记录中。
  8.继续执行线程1的代码。
  9.线程2进行自旋操作获得轻量级锁。

轻量级锁升级:
  1.如果线程2自旋后获取锁失败,或者在线程2自旋的时候,线程3也来获取锁,那么该锁会升级为重量级锁。当锁处于这个状态下时,其他线程试图获取锁时都会被阻塞住,当持有锁的线程释放锁之后会唤醒这些线程,被唤醒的线程就会进行新一轮的竞争。

上一篇 下一篇

猜你喜欢

热点阅读