从OpenJdk分析Object,wait(),notify(),notifyAll()

我们知道多线程争抢临界资源,首先先进入entryList队列,然后去争抢实例对象对应的监视器的锁,例如下图ObjectMonitor结构。

waitSet是监视器上等待的线程集合。自己获得锁之后调用wait()方法。

EntryList是阻塞线程集合。ObjectWaiter是链表结构。

 

(1)wait源码解析

void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {

   Thread * const Self = THREAD ;// 将当前线程赋值给Selft

   /*************/

ObjectWaiter node(Self); //将当前线程转化为ObjectWaiter
Thread::SpinAcquire (&_WaitSetLock, "WaitSet - add") ;//先自旋
AddWaiter (&node) ;//线程加入waitSet队列
Thread::SpinRelease (&_WaitSetLock) ;
_waiters++;                  // increment the number of waiters
 _recursions = 0;             // set the recursion level to be 1
exit (true, Self) ;                    // exit the monitor

 

(2)notify源码解析

void ObjectMonitor::notify(TRAPS) {

  CHECK_OWNER();

  if (_WaitSet == NULL) {  //若waitSet为空,直接返回

     TEVENT (Empty-Notify) ;

     return ;

  }

ObjectWaiter * iterator = DequeueWaiter() ;

  if (iterator != NULL) {

    if (Policy == 0) {   

     /*******/

     } else if( Policy == 1){

/*******/

 

}

}

结合Object的notify javaDoc,我们知道若一个线程在等待,那么他们中的一个将被唤醒,选择策略在实现上是任意的。在源码中对应各种Policy

 

(3)notifyAll源码解析

       nofifyAll会唤醒ObjectWaiter列表所有对象

void ObjectMonitor::notifyAll(TRAPS) {

   ObjectWaiter* iterator;

   if (_WaitSet == NULL) {

      TEVENT (Empty-NotifyAll) ;

      return ;

  }

  for (;;) { //for循环唤醒所有的waitSet中的ObjectWaiter

  

 

(4)synchronized锁

  从Jdk1.6开始, synchronized锁d的实现发生了很大变化,jvm引入了相应的优化手段提升性能。这种提升涉及到偏向锁,轻量级锁,重量级锁等从而避免锁的竞争带来的用户态和内核态的切换。锁的优化是由java对象头的中的标志位来实现的,锁的访问与改变都和java对象头息息相关。

  从jdk1.6之后,对象实例在堆中化分3个组成部分:对象头,实例数据,对齐填充。对象头组要有3块组成:(1)Mark word (2)指向类的指针(3)数组长度

  Mark word它记录了对象,锁以及垃圾回收相关信息,(1)无锁标记(2)偏向锁(3)轻量级锁(4)重量级锁(5)GC标记。

  锁的演化由经历: 无锁 ==>偏向锁 ==>轻量级锁 ==>重量级锁

  锁的升级是根据偏向锁标志位是否和Mark Word中锁标志位一致来达成的。

发布了182 篇原创文章 · 获赞 45 · 访问量 25万+

猜你喜欢

转载自blog.csdn.net/u014172271/article/details/100006112