目录

1、AddWaiter / DequeueWaiter /DequeueSpecificWaiter

2、wait

3、notify

4、notifyAll

5、exit

6、try_enter / complete_exit

7、总结


本篇博客继续上一篇《Hotspot 重量级锁ObjectMonitor(一) 源码解析》将ObjectMonitor的其他关键方法的实现。

1、AddWaiter / DequeueWaiter /DequeueSpecificWaiter

AddWaiter方法用于将目标ObjectWaiter加入到双向循环链表中,DequeueWaiter用于移除链表头_WaitSet对应的节点,该节点是最早加入到链表的,即按照加入链表的先后顺序依次从链表中移除,DequeueSpecificWaiter用于移除指定节点,不一定是_WaitSet对应的节点。其实现如下:

inline void ObjectMonitor::AddWaiter(ObjectWaiter* node) {assert(node != NULL, "should not dequeue NULL node");assert(node->_prev == NULL, "node already in list");assert(node->_next == NULL, "node already in list");//将目标节点放入一个双向的循环链表中if (_WaitSet == NULL) {//如果_WaitSet还是空的,当前节点就是第一个_WaitSet = node;node->_prev = node;node->_next = node;} else {//如果_WaitSet不是空的,将其插入到head的prev节点上ObjectWaiter* head = _WaitSet ;ObjectWaiter* tail = head->_prev;assert(tail->_next == head, "invariant check");//注意tail在初始状态下就是head,所以插入第二个节点时修改next属性,实际是修改head的next属性tail->_next = node;head->_prev = node;node->_next = head;node->_prev = tail;}
}inline ObjectWaiter* ObjectMonitor::DequeueWaiter() {// dequeue the very first waiterObjectWaiter* waiter = _WaitSet;if (waiter) {//如果_WaitSet为不空DequeueSpecificWaiter(waiter);}return waiter;
}inline void ObjectMonitor::DequeueSpecificWaiter(ObjectWaiter* node) {assert(node != NULL, "should not dequeue NULL node");assert(node->_prev != NULL, "node already removed from list");assert(node->_next != NULL, "node already removed from list");//从_WaitSet中取出一个ObjectWaiter,实际就是取出_WaitSet对应的head节点,该//节点是最早加入到链表中的ObjectWaiter* next = node->_next;if (next == node) {//_WaitSet只有一个节点assert(node->_prev == node, "invariant check");_WaitSet = NULL;} else {//将node从链表中移除ObjectWaiter* prev = node->_prev;assert(prev->_next == node, "invariant check");assert(next->_prev == node, "invariant check");next->_prev = prev;prev->_next = next;if (_WaitSet == node) {//如果移除的就是_WaitSet,将next置为_WaitSet_WaitSet = next;}}//相关属性置为nullnode->_next = NULL;node->_prev = NULL;
}

上述逻辑可以结合以下用例来理解,如下:

//依次添加node,node2,node3,node4,node5 5个节点时各节点的引用关系
prev        next
----------------
node  node  node
=================
node2 node  node2
node  node2 node
=================
node  node2 node3
node3 node  node2
node2 node3 node
=================
node2 node3 node4
node4 node  node2
node3 node4  node
node  node2 node3 //node2节点的引用关系不变
=================
node3 node4 node5
node5 node  node2
node4 node5 node
node  node2 node3 //node2和node3节点的引用关系不变
node2 node3 node4删除node节点后node2作为_WaitSet
================
node4 node5 node2
node5 node2 node3
node  node2 node3 //node2和node3节点的引用关系不变
node2 node3 node4

2、wait

wait方法是Object的wait方法的底层实现,该方法会创建一个ObjectWaiter并加入到链表中,然后释放占有的锁,让当前线程休眠,当当前线程因为等待超时,被中断或者被其他线程唤醒时就再次抢占锁,抢占逻辑就是之前的enter方法,抢占成功后wait方法退出。

void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {//获取当前线程Thread * const Self = THREAD ;assert(Self->is_Java_thread(), "Must be Java thread!");JavaThread *jt = (JavaThread *)THREAD;//初始化配置,如果已经初始化则返回DeferredInitialize () ;//检查当前线程是否获取了锁,如果没有则抛出异常CHECK_OWNER();EventJavaMonitorWait event;//如果线程被中断了且不是因为未处理异常导致的if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {//发布JVMTI事件if (JvmtiExport::should_post_monitor_waited()) {JvmtiExport::post_monitor_waited(jt, this, false);}if (event.should_commit()) {post_monitor_wait_event(&event, 0, millis, false);}TEVENT (Wait - Throw IEX) ;//抛出异常THROW(vmSymbols::java_lang_InterruptedException());return ;}TEVENT (Wait) ;assert (Self->_Stalled == 0, "invariant") ;//设置属性,记录当前线程等待的ObjectMonitorSelf->_Stalled = intptr_t(this) ;jt->set_current_waiting_monitor(this);//创建ObjectWaiter,将其状态置为TS_WAITObjectWaiter node(Self);node.TState = ObjectWaiter::TS_WAIT ;Self->_ParkEvent->reset() ;OrderAccess::fence();          // ST into Event; membar ; LD interrupted-flag//获取操作ObjectWaiter链表的锁_WaitSetLockThread::SpinAcquire (&_WaitSetLock, "WaitSet - add") ;//将当前节点插入到ObjectWaiter链表中AddWaiter (&node) ;//释放锁Thread::SpinRelease (&_WaitSetLock) ;//SyncFlags默认为0if ((SyncFlags & 4) == 0) {_Responsible = NULL ;}intptr_t save = _recursions; // record the old recursion count//等待的线程数加1_waiters++;                  // increment the number of waiters_recursions = 0;             // set the recursion level to be 1//释放该锁exit (true, Self) ;                    // exit the monitorguarantee (_owner != Self, "invariant") ;// TODO-FIXME: change the following logic to a loop of the form//   while (!timeout && !interrupted && _notified == 0) park()int ret = OS_OK ;int WasNotified = 0 ;{ // State transition wrappersOSThread* osthread = Self->osthread();//修改线程状态为OBJECT_WAITOSThreadWaitState osts(osthread, true);{//修改线程状态从_thread_in_vm到_thread_blockedThreadBlockInVM tbivm(jt);// Thread is in thread_blocked state and oop access is unsafe.jt->set_suspend_equivalent();if (interruptible && (Thread::is_interrupted(THREAD, false) || HAS_PENDING_EXCEPTION)) {// Intentionally empty} elseif (node._notified == 0) { //_notified为0表示没有其他线程唤醒//将当前线程park,让其处于休眠状态if (millis <= 0) {Self->_ParkEvent->park () ;} else {ret = Self->_ParkEvent->park (millis) ;}}//当前线程从park状态被唤醒了//ExitSuspendEquivalent默认返回falseif (ExitSuspendEquivalent (jt)) {// TODO-FIXME: add -- if succ == Self then succ = null.jt->java_suspend_self();}} //退出代码块时会切换线程状态 _thread_blocked -> _thread_in_vm//如果是线程被中断或者等待超时则状态是TS_WAIT,如果是被nofity唤醒的则应该是TS_RUN if (node.TState == ObjectWaiter::TS_WAIT) {//获取锁Thread::SpinAcquire (&_WaitSetLock, "WaitSet - unlink") ;if (node.TState == ObjectWaiter::TS_WAIT) {//如果是TS_WAIT,则将其从链表中移除DequeueSpecificWaiter (&node) ;       // unlink from WaitSetassert(node._notified == 0, "invariant");//将状态置为TS_RUNnode.TState = ObjectWaiter::TS_RUN ;}//释放锁Thread::SpinRelease (&_WaitSetLock) ;}guarantee (node.TState != ObjectWaiter::TS_WAIT, "invariant") ;//让修改立即生效OrderAccess::loadload() ;if (_succ == Self) _succ = NULL ;WasNotified = node._notified ;// post monitor waited event. Note that this is past-tense, we are done waiting.if (JvmtiExport::should_post_monitor_waited()) {JvmtiExport::post_monitor_waited(jt, this, ret == OS_TIMEOUT);if (node._notified != 0 && _succ == Self) {node._event->unpark();}}if (event.should_commit()) {post_monitor_wait_event(&event, node._notifier_tid, millis, ret == OS_TIMEOUT);}OrderAccess::fence() ;assert (Self->_Stalled != 0, "invariant") ;Self->_Stalled = 0 ;assert (_owner != Self, "invariant") ;ObjectWaiter::TStates v = node.TState ;if (v == ObjectWaiter::TS_RUN) {//重新获取该锁enter (Self) ;} else {//该ObjectWaiter已经被唤醒了,但是等待获取锁的时候线程被中断了guarantee (v == ObjectWaiter::TS_ENTER || v == ObjectWaiter::TS_CXQ, "invariant") ;ReenterI (Self, &node) ;node.wait_reenter_end(this);}guarantee (node.TState == ObjectWaiter::TS_RUN, "invariant") ;assert    (_owner == Self, "invariant") ;assert    (_succ != Self , "invariant") ;} // OSThreadWaitState()jt->set_current_waiting_monitor(NULL);guarantee (_recursions == 0, "invariant") ;_recursions = save;     // restore the old recursion count_waiters--;             // decrement the number of waiters// Verify a few postconditionsassert (_owner == Self       , "invariant") ;assert (_succ  != Self       , "invariant") ;assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;if (SyncFlags & 32) {OrderAccess::fence() ;}//如果不是因为notify被唤醒if (!WasNotified) {// 可能因为等待超时或者Thread.interrupt()被唤醒if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {TEVENT (Wait - throw IEX from epilog) ;//如果线程中断则抛出异常THROW(vmSymbols::java_lang_InterruptedException());}}
}#define CHECK_OWNER()                                                             \do {                                                                            \if (THREAD != _owner) {                                                       \//如果owner属性不是当前线程if (THREAD->is_lock_owned((address) _owner)) {                              \//如果owner属性位于当前线程栈帧中,说明该锁是由轻量级锁膨胀来的//修改owner属性为当前线程_owner = THREAD ;  /* Convert from basiclock addr to Thread addr */       \_recursions = 0;                                                          \OwnerIsThread = 1 ;                                                       \} else {                                                                    \//当前线程没有获取锁,则抛出异常TEVENT (Throw IMSX) ;                                                     \THROW(vmSymbols::java_lang_IllegalMonitorStateException());               \}                                                                           \}                                                                             \} while (false)bool Thread::is_interrupted(Thread* thread, bool clear_interrupted) {trace("is_interrupted", thread);debug_only(check_for_dangling_thread_pointer(thread);)// 判断其是否被中断,如果是且clear_interrupted为true,则将其中断标识清除掉return os::is_interrupted(thread, clear_interrupted);
}bool os::is_interrupted(Thread* thread, bool clear_interrupted) {assert(Thread::current() == thread || Threads_lock->owned_by_self(),"possibility of dangling Thread pointer");//获取关联的原生线程OSThread* osthread = thread->osthread();//获取其是否被中断bool interrupted = osthread->interrupted();if (interrupted && clear_interrupted) {//清除被中断标识osthread->set_interrupted(false);}return interrupted;
}//ReenterI和EnterI的逻辑基本相同,用于获取对象锁
void ATTR ObjectMonitor::ReenterI (Thread * Self, ObjectWaiter * SelfNode) {assert (Self != NULL                , "invariant") ;assert (SelfNode != NULL            , "invariant") ;assert (SelfNode->_thread == Self   , "invariant") ;assert (_waiters > 0                , "invariant") ;//校验目标对象的对象头就是当前ObjectMonitor的指针assert (((oop)(object()))->mark() == markOopDesc::encode(this) , "invariant") ;assert (((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant") ;JavaThread * jt = (JavaThread *) Self ;int nWakeups = 0 ;for (;;) {ObjectWaiter::TStates v = SelfNode->TState ;//校验状态guarantee (v == ObjectWaiter::TS_ENTER || v == ObjectWaiter::TS_CXQ, "invariant") ;assert    (_owner != Self, "invariant") ;//尝试获取锁if (TryLock (Self) > 0) break ;//尝试自旋获取锁if (TrySpin (Self) > 0) break ;TEVENT (Wait Reentry - parking) ;{   //修改线程状态OSThreadContendState osts(Self->osthread());ThreadBlockInVM tbivm(jt);jt->set_suspend_equivalent();//SyncFlags默认是0if (SyncFlags & 1) {Self->_ParkEvent->park ((jlong)1000) ;} else {Self->_ParkEvent->park () ;}// were we externally suspended while we were waiting?for (;;) {//ExitSuspendEquivalent默认返回falseif (!ExitSuspendEquivalent (jt)) break ;if (_succ == Self) { _succ = NULL; OrderAccess::fence(); }jt->java_suspend_self();jt->set_suspend_equivalent();}}//尝试获取锁if (TryLock(Self) > 0) break ;TEVENT (Wait Reentry - futile wakeup) ;++ nWakeups ;// Assuming this is not a spurious wakeup we'll normally// find that _succ == Self.if (_succ == Self) _succ = NULL ;// Invariant: after clearing _succ a contending thread// *must* retry  _owner before parking.OrderAccess::fence() ;if (ObjectMonitor::_sync_FutileWakeups != NULL) {ObjectMonitor::_sync_FutileWakeups->inc() ;}}//for循环结束//for循环结束,已经获取了锁assert (_owner == Self, "invariant") ;assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;//从链表中移除UnlinkAfterAcquire (Self, SelfNode) ;if (_succ == Self) _succ = NULL ;assert (_succ != Self, "invariant") ;//修改状态为TS_RUNSelfNode->TState = ObjectWaiter::TS_RUN ;OrderAccess::fence() ;      // see comments at the end of EnterI()
}

3、notify

notify方法时Object的notify方法的底层实现,用于“唤醒”WaitSet链表头对应的线程,即最早加入到该链表的等待线程,注意在默认配置下(默认的处理策略是2,不同策略的处理逻辑不同),并不会直接unpark该线程,而是将其加入到cxq链表的前面,相当于调用了一次EnterI方法。加入到cxq链表后,当关联的锁被释放了就会unpark该线程,注意只是唤醒,然后该线程调用enter方法抢占锁,因此此时可能有其他线程在同时调用enter方法抢占锁。

void ObjectMonitor::notify(TRAPS) {//检查当前线程是否占用该锁,如果没有抛出异常CHECK_OWNER();if (_WaitSet == NULL) {//如果没有等待的线程则退出TEVENT (Empty-Notify) ;return ;}//Knob_MoveNotifyee属性默认是2int Policy = Knob_MoveNotifyee ;//获取锁Thread::SpinAcquire (&_WaitSetLock, "WaitSet - notify") ;//将链表头元素移除并返回ObjectWaiter * iterator = DequeueWaiter() ;if (iterator != NULL) {TEVENT (Notify1 - Transfer) ;guarantee (iterator->TState == ObjectWaiter::TS_WAIT, "invariant") ;guarantee (iterator->_notified == 0, "invariant") ;if (Policy != 4) {//将状态置为TS_ENTERiterator->TState = ObjectWaiter::TS_ENTER ;}//_notified置为1表示该ObjectWaiter被唤醒了iterator->_notified = 1 ;Thread * Self = THREAD;//记录当前线程IDiterator->_notifier_tid = Self->osthread()->thread_id();ObjectWaiter * List = _EntryList ;if (List != NULL) {assert (List->_prev == NULL, "invariant") ;assert (List->TState == ObjectWaiter::TS_ENTER, "invariant") ;assert (List != iterator, "invariant") ;}//根据不同的策略执行不同的处理if (Policy == 0) {       //将iterator插入到_EntryList头元素的前面if (List == NULL) {iterator->_next = iterator->_prev = NULL ;_EntryList = iterator ;} else {List->_prev = iterator ;iterator->_next = List ;iterator->_prev = NULL ;_EntryList = iterator ;}} elseif (Policy == 1) {      //将iterator插入到_EntryList链表的末尾if (List == NULL) {iterator->_next = iterator->_prev = NULL ;_EntryList = iterator ;} else {ObjectWaiter * Tail ;//不断遍历找到链表最后一个元素for (Tail = List ; Tail->_next != NULL ; Tail = Tail->_next) ;assert (Tail != NULL && Tail->_next == NULL, "invariant") ;Tail->_next = iterator ;iterator->_prev = Tail ;iterator->_next = NULL ;}} elseif (Policy == 2) {      //将iterator插入到_cxq头元素的前面// prepend to cxqif (List == NULL) {iterator->_next = iterator->_prev = NULL ;_EntryList = iterator ;} else {iterator->TState = ObjectWaiter::TS_CXQ ;for (;;) {ObjectWaiter * Front = _cxq ;iterator->_next = Front ;if (Atomic::cmpxchg_ptr (iterator, &_cxq, Front) == Front) {break ;}}}} elseif (Policy == 3) {      //将iterator插入到_cxq链表末尾的后面iterator->TState = ObjectWaiter::TS_CXQ ;for (;;) {ObjectWaiter * Tail ;Tail = _cxq ;if (Tail == NULL) {iterator->_next = NULL ;if (Atomic::cmpxchg_ptr (iterator, &_cxq, NULL) == NULL) {break ;}} else {//往后遍历找到最后一个元素while (Tail->_next != NULL) Tail = Tail->_next ;Tail->_next = iterator ;iterator->_prev = Tail ;iterator->_next = NULL ;break ;}}} else {//将等待的线程直接unpark唤醒ParkEvent * ev = iterator->_event ;iterator->TState = ObjectWaiter::TS_RUN ;OrderAccess::fence() ;ev->unpark() ;}if (Policy < 4) {//修改线程状态,记录锁竞争开始iterator->wait_reenter_begin(this);}} //if结束//释放锁Thread::SpinRelease (&_WaitSetLock) ;if (iterator != NULL && ObjectMonitor::_sync_Notifications != NULL) {//增加计数ObjectMonitor::_sync_Notifications->inc() ;}
}

4、notifyAll

notifyAll方法就是Object的notifyAll方法的底层实现,对单个ObjectWaiter其处理逻辑跟notify是一致的,相比notify的实现就是增加了一个for循环,会不断的从_WaitSet链表中移除头元素,然后执行notify的处理逻辑,直到_WaitSet链表为空退出循环。

void ObjectMonitor::notifyAll(TRAPS) {//检查当前线程是否占用该锁,如果没有抛出异常CHECK_OWNER();ObjectWaiter* iterator;if (_WaitSet == NULL) {//如果没有等待的线程则退出TEVENT (Empty-NotifyAll) ;return ;}//Knob_MoveNotifyee属性默认是2int Policy = Knob_MoveNotifyee ;int Tally = 0 ;//获取锁Thread::SpinAcquire (&_WaitSetLock, "WaitSet - notifyall") ;//if变成for循环for (;;) {//获取头部元素,头部节点为最早加入到链表中的节点iterator = DequeueWaiter () ;//如果为空则终止循环if (iterator == NULL) break ;TEVENT (NotifyAll - Transfer1) ;//增加计数++Tally ;guarantee (iterator->TState == ObjectWaiter::TS_WAIT, "invariant") ;guarantee (iterator->_notified == 0, "invariant") ;//_notified置为1表示该ObjectWaiter被唤醒了iterator->_notified = 1 ;Thread * Self = THREAD;//记录当前线程IDiterator->_notifier_tid = Self->osthread()->thread_id();if (Policy != 4) {//将状态置为TS_ENTERiterator->TState = ObjectWaiter::TS_ENTER ;}//根据不同的策略执行不同的处理ObjectWaiter * List = _EntryList ;if (List != NULL) {assert (List->_prev == NULL, "invariant") ;assert (List->TState == ObjectWaiter::TS_ENTER, "invariant") ;assert (List != iterator, "invariant") ;}if (Policy == 0) {      //将iterator插入到_EntryList头元素的前面if (List == NULL) {iterator->_next = iterator->_prev = NULL ;_EntryList = iterator ;} else {List->_prev = iterator ;iterator->_next = List ;iterator->_prev = NULL ;_EntryList = iterator ;}} elseif (Policy == 1) {      //将iterator插入到_EntryList链表的末尾if (List == NULL) {iterator->_next = iterator->_prev = NULL ;_EntryList = iterator ;} else {ObjectWaiter * Tail ;for (Tail = List ; Tail->_next != NULL ; Tail = Tail->_next) ;assert (Tail != NULL && Tail->_next == NULL, "invariant") ;Tail->_next = iterator ;iterator->_prev = Tail ;iterator->_next = NULL ;}} elseif (Policy == 2) {     //将iterator插入到_cxq头元素的前面// prepend to cxqiterator->TState = ObjectWaiter::TS_CXQ ;for (;;) {ObjectWaiter * Front = _cxq ;iterator->_next = Front ;if (Atomic::cmpxchg_ptr (iterator, &_cxq, Front) == Front) {break ;}}} elseif (Policy == 3) {      //将iterator插入到_cxq链表末尾的后面iterator->TState = ObjectWaiter::TS_CXQ ;for (;;) {ObjectWaiter * Tail ;Tail = _cxq ;if (Tail == NULL) {iterator->_next = NULL ;if (Atomic::cmpxchg_ptr (iterator, &_cxq, NULL) == NULL) {break ;}} else {while (Tail->_next != NULL) Tail = Tail->_next ;Tail->_next = iterator ;iterator->_prev = Tail ;iterator->_next = NULL ;break ;}}} else {//将等待的线程直接unpark唤醒ParkEvent * ev = iterator->_event ;iterator->TState = ObjectWaiter::TS_RUN ;OrderAccess::fence() ;ev->unpark() ;}if (Policy < 4) {//修改线程状态,记录锁竞争开始iterator->wait_reenter_begin(this);}}//for循环结束//释放锁Thread::SpinRelease (&_WaitSetLock) ;if (Tally != 0 && ObjectMonitor::_sync_Notifications != NULL) {//增加计数ObjectMonitor::_sync_Notifications->inc(Tally) ;}
}

5、exit

exit用于释放锁,即将owner属性置为NULL,默认配置下会通过unpark唤醒_EntryList链表头部节点对应的等待线程,如果EntryList链表为空,则将cxq链表中的元素加入到EntryList链表中且顺序保持不变,即优先唤醒最近等待的线程。注意exit方法并不会因为安全点同步而阻塞,exit方法退出后继续执行,无论解释执行或者编译执行则会都被阻塞;exit方式释放锁后,被唤醒的线程占用了该锁,在enter方法获取锁准备切换线程状态时会被阻塞。

//第一个参数not_suspended用于debug的,可以忽略
void ATTR ObjectMonitor::exit(bool not_suspended, TRAPS) {Thread * Self = THREAD ;if (THREAD != _owner) {if (THREAD->is_lock_owned((address) _owner)) {//如果owner位于当前线程调用栈帧,说明该锁是轻量级锁膨胀来的assert (_recursions == 0, "invariant") ;//修改owner属性_owner = THREAD ;_recursions = 0 ;OwnerIsThread = 1 ;} else {//其他线程占用该锁,直接返回TEVENT (Exit - Throw IMSX) ;assert(false, "Non-balanced monitor enter/exit!");if (false) {THROW(vmSymbols::java_lang_IllegalMonitorStateException());}return;}}if (_recursions != 0) {//不等于0说明是嵌套加锁,将_recursions减1即可返回_recursions--;        // this is simple recursive enterTEVENT (Inflated exit - recursive) ;return ;}// SyncFlags默认值是0if ((SyncFlags & 4) == 0) {_Responsible = NULL ;}for (;;) {assert (THREAD == _owner, "invariant") ;//Knob_ExitPolicy默认值是0if (Knob_ExitPolicy == 0) {//将_owner属性置为NULL,释放锁,如果某个线程正在自旋抢占该锁,则会抢占成功//即这种策略会优先保证通过自旋抢占锁的线程获取锁,而其他处于等待队列中的线程则靠后OrderAccess::release_store_ptr (&_owner, NULL) ;   // drop the lock//让修改立即生效OrderAccess::storeload() ;                         // See if we need to wake a successorif ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {//如果_EntryList或者cxq链表都是空的,则直接返回TEVENT (Inflated exit - simple egress) ;return ;}TEVENT (Inflated exit - complex egress) ;//如果_EntryList或者cxq链表不是空的,则原子的设置owner属性为当前线程,尝试抢占锁if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {//抢占失败则返回,等占用该锁的线程释放后再处理链表中的等待线程return ;}TEVENT (Exit - Reacquired) ;} else {if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {OrderAccess::release_store_ptr (&_owner, NULL) ;   // drop the lockOrderAccess::storeload() ;// Ratify the previously observed values.if (_cxq == NULL || _succ != NULL) {TEVENT (Inflated exit - simple egress) ;return ;}//有可能cxq插入了一个新节点,导致上面的if不成立,需要重新获取锁if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {TEVENT (Inflated exit - reacquired succeeded) ;return ;}TEVENT (Inflated exit - reacquired failed) ;} else {//如果_EntryList或者cxq链表不是空的则不释放锁,避免二次抢占锁,即优先处理等待队列中的线程TEVENT (Inflated exit - complex egress) ;}}guarantee (_owner == THREAD, "invariant") ;ObjectWaiter * w = NULL ;//Knob_QMode的默认值是0int QMode = Knob_QMode ;if (QMode == 2 && _cxq != NULL) {w = _cxq ;assert (w != NULL, "invariant") ;assert (w->TState == ObjectWaiter::TS_CXQ, "Invariant") ;//通过unpark唤醒cxq对应的线程,唤醒后会将cxq从链表中移除ExitEpilog (Self, w) ;return ;}if (QMode == 3 && _cxq != NULL) {//将cxq链表中的元素插入到_EntryList链表的末尾w = _cxq ;for (;;) {assert (w != NULL, "Invariant") ;//将_cxq原子的置为NULL,如果失败则更新w,重新尝试直到成功为止//置为NULL后,如果有新的节点插入进来就形成了一个新的cxq链表ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;if (u == w) break ;w = u ;}assert (w != NULL              , "invariant") ;ObjectWaiter * q = NULL ;ObjectWaiter * p ;//遍历cxq中的所有节点,将其置为TS_ENTERfor (p = w ; p != NULL ; p = p->_next) {guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;p->TState = ObjectWaiter::TS_ENTER ;p->_prev = q ;q = p ;}ObjectWaiter * Tail ;//遍历_EntryList找到末尾元素,将w插入到后面for (Tail = _EntryList ; Tail != NULL && Tail->_next != NULL ; Tail = Tail->_next) ;if (Tail == NULL) {_EntryList = w ;} else {Tail->_next = w ;w->_prev = Tail ;}}if (QMode == 4 && _cxq != NULL) {//将cxq链表中的元素插入到_EntryList链表的头部w = _cxq ;for (;;) {assert (w != NULL, "Invariant") ;//将_cxq原子的置为NULL,如果失败则更新w,重新尝试直到成功为止ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;if (u == w) break ;w = u ;}assert (w != NULL              , "invariant") ;ObjectWaiter * q = NULL ;ObjectWaiter * p ;//遍历cxq中的所有节点,将其置为TS_ENTERfor (p = w ; p != NULL ; p = p->_next) {guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;p->TState = ObjectWaiter::TS_ENTER ;p->_prev = q ;q = p ;}//插入到_EntryList的头部if (_EntryList != NULL) {q->_next = _EntryList ;_EntryList->_prev = q ;}_EntryList = w ;}w = _EntryList  ;if (w != NULL) {//通过unpark唤醒w对应的线程,唤醒后会该线程会负责将w从EntryList链表中移除assert (w->TState == ObjectWaiter::TS_ENTER, "invariant") ;ExitEpilog (Self, w) ;return ;}//如果_EntryList为空w = _cxq ;if (w == NULL) continue ;//如果cxq为空则重新循环,不会进入此分支//cxq不为NULLfor (;;) {assert (w != NULL, "Invariant") ;//将cxq原子的修改为NULLObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;if (u == w) break ;w = u ;}TEVENT (Inflated exit - drain cxq into EntryList) ;assert (w != NULL              , "invariant") ;assert (_EntryList  == NULL    , "invariant") ;if (QMode == 1) {//遍历cxq中的元素将其加入到_EntryList中,注意顺序跟cxq中是返的ObjectWaiter * s = NULL ;ObjectWaiter * t = w ;ObjectWaiter * u = NULL ;while (t != NULL) {guarantee (t->TState == ObjectWaiter::TS_CXQ, "invariant") ;t->TState = ObjectWaiter::TS_ENTER ;u = t->_next ;t->_prev = u ;t->_next = s ;s = t;t = u ;}_EntryList  = s ;assert (s != NULL, "invariant") ;} else {// QMode == 0 or QMode == 2//遍历cxq中的元素将其加入到_EntryList中,注意此时cxq链表的头元素被赋值给EntryList_EntryList = w ;ObjectWaiter * q = NULL ;ObjectWaiter * p ;//cxq中的元素是通过next属性串联起来的,prev属性没有,此处遍历加上prev属性//当EntryList头元素被移除了是取next属性作为EntryListfor (p = w ; p != NULL ; p = p->_next) {guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;p->TState = ObjectWaiter::TS_ENTER ;p->_prev = q ;q = p ;}}if (_succ != NULL) continue;w = _EntryList  ;if (w != NULL) {guarantee (w->TState == ObjectWaiter::TS_ENTER, "invariant") ;//唤醒w对应的线程ExitEpilog (Self, w) ;return ;}}
}void ObjectMonitor::ExitEpilog (Thread * Self, ObjectWaiter * Wakee) {assert (_owner == Self, "invariant") ;//Knob_SuccEnabled默认是1,succ表示很有可能占用该锁的线程_succ = Knob_SuccEnabled ? Wakee->_thread : NULL ;ParkEvent * Trigger = Wakee->_event ;Wakee  = NULL ;//将owner属性置为NULLOrderAccess::release_store_ptr (&_owner, NULL) ;OrderAccess::fence() ;                               // ST _owner vs LD in unpark()if (SafepointSynchronize::do_call_back()) {TEVENT (unpark before SAFEPOINT) ;}DTRACE_MONITOR_PROBE(contended__exit, this, object(), Self);//唤醒目标线程Trigger->unpark() ;if (ObjectMonitor::_sync_Parks != NULL) {//增加计数ObjectMonitor::_sync_Parks->inc() ;}
}

6、try_enter / complete_exit

try_enter用于实现Unsafe类的tryMonitorEnter方法,会尝试获取锁,如果获取失败则直接返回false;complete_exit用于释放目标锁,在嵌套加锁的情形下只需要调用complete_exit一次即可,如果是exit则需要调用多次。

bool ObjectMonitor::try_enter(Thread* THREAD) {if (THREAD != _owner) {if (THREAD->is_lock_owned ((address)_owner)) {//如果该线程已经占有了该锁,该锁由轻量级锁膨胀而来assert(_recursions == 0, "internal state error");//修改owner等属性_owner = THREAD ;_recursions = 1 ;OwnerIsThread = 1 ;return true;}if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {//原子的设置owner属性,修改失败return false;}//修改成功return true;} else {//当前线程已经占有该锁,将记录嵌套加锁的计数器加1_recursions++;return true;}
}intptr_t ObjectMonitor::complete_exit(TRAPS) {Thread * const Self = THREAD;assert(Self->is_Java_thread(), "Must be Java thread!");JavaThread *jt = (JavaThread *)THREAD;DeferredInitialize();if (THREAD != _owner) {if (THREAD->is_lock_owned ((address)_owner)) {//如果是轻量级锁膨胀来的assert(_recursions == 0, "internal state error");_owner = THREAD ;   /* Convert from basiclock addr to Thread addr */_recursions = 0 ;OwnerIsThread = 1 ;}}guarantee(Self == _owner, "complete_exit not owner");intptr_t save = _recursions; // record the old recursion count//_recursions置为0,即嵌套加锁的情形下不需要多次调用exit了_recursions = 0;        // set the recursion level to be 0//释放该锁exit (true, Self) ;           // exit the monitorguarantee (_owner != Self, "invariant");return save;
}

7、总结

ObjectMonitor维护了三个ObjectWaiter链表,分别是cxq链表、EntryList链表和WaitSet链表,对应链表中ObjectWaiter的状态分别是TS_CXQ,TS_ENTER和TS_WAIT。调用enter方法时,如果自旋获取锁失败就会创建一个ObjectWaiter并加入到cxq链表中,某个已经获取锁的线程调用wait方法会创建一个ObjectWaiter并加入到WaitSet链表中,当某个线程调用notify/notifyAll方法“唤醒”该线程时,会将该ObjectWaiter从WaitSet链表中移除然后加入到cxq链表头。当某个获取锁的线程释放锁时,就会唤醒EntryList链表头对应的线程,如果EntryList链表为空,则将此时的cxq链表中的元素整体转移到EntryList链表中,然后同样的唤醒EntryList链表头对应的线程,被唤醒后该线程一样调用enter方法抢占锁。

Hotspot 重量级锁ObjectMonitor(二) 源码解析相关推荐

  1. Hotspot 对象引用Reference和Finalizer 源码解析

    目录 一.Reference 1.SoftReference / WeakReference / PhantomReference 2.定义 3.ReferenceHandler 4.Cleaner ...

  2. Hotspot 垃圾回收之GenCollectedHeap 源码解析

    目录 1.定义 2.构造方法 / initialize / post_initialize 3.do_collection 4.do_full_collection 5.collect 6.VM_Ge ...

  3. Hotspot 重量级锁ObjectMonitor(一) 源码解析

    目录 1.定义 2.TrySpin_VaryDuration 3.ObjectWaiter 4.EnterI 5.JavaThreadBlockedOnMonitorEnterState / OSTh ...

  4. Hotspot 垃圾回收之VM_Operation 源码解析

    目录 一.VM_Operation ​二.VMThread 1.定义 2.create / destroy 3.run / wait_for_vm_thread_exit 4.loop 5.VMThr ...

  5. Hotspot 垃圾回收之oop_iterate(二) 源码解析

    目录 1.java.lang.Class 1.1.Class实例中oop_size.klass等属性是哪来的? 1.2._offset_of_static_fields 1.3 为什么从_offset ...

  6. 线程池解析(三)——Worker源码解析

    相关文章 线程池解析(一)--概念总结 线程池解析(二)--execute.addWorker源码解析 线程池解析(三)--Worker源码解析 线程池解析(四)--submit源码解析(Runnab ...

  7. Hotspot 垃圾回收之ReferenceProcessor(二) 源码解析

    目录 1.process_discovered_reflist 2.process_phaseJNI 3.process_discovered_references 4.preclean_discov ...

  8. 源码解析-偏向锁撤销流程解读

    一.单个偏向锁的撤销 源码链接:http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/9ce27f0a4683/src/share/vm/runtim ...

  9. Mybatis源码解析《二》

    导语 在前一篇文章Mybatis源码解析<一>中,已经简单了捋了一下mybatis核心文件和mapper配置文件的一个基本的解析流程,这是理解mybatis的基本,和spring中的配置文 ...

最新文章

  1. CLOCs:3D目标检测多模态融合之Late-Fusion
  2. 杭电ACM刷题(1):1002,A + B Problem II
  3. 前端开发学习二——由JSON和Object Literal Notation引起的思考
  4. 决定投身书海,WEB前端开发书籍推荐
  5. Android—APK、JVM-Dalvik-ART
  6. JavaScript将iframe中控件的值传到主页面控件中
  7. python语言能做什么-Python是什么_python能做什么
  8. 利用diyUpload做多图片上传及预览
  9. adobe premiere 不支持的视频驱动程序
  10. 计算机的开机自检由什么程序完成,开机自检,教您怎么取消电脑上的开机自检...
  11. 社会生活——《哥哥又逃票了》
  12. 使用跳板机在Pycharm上配置内网服务器
  13. 一步步学习SPD2010--第一章节--探索SPD2010(3)--理解SharePoint Designer 2010新功能
  14. 背景图片如何自适应屏幕
  15. 【MDCC 2016】iOS开发峰会回顾:实战Coding演示 技术大牛带你起飞
  16. Windows10系统安装好用的截图软件--snipaste
  17. 密码(mima)的答案
  18. shape格式、tiff格式地图免费下载网站转载
  19. 毒液:致命守护者HDTC1080清晰英语中字
  20. python数据分析:流量数据化运营(中)——流量数据波动原因下探分析

热门文章

  1. vmware最小化安装
  2. Android多进程从头讲到尾,吐血整理
  3. Spark项目实战:飞机延误预测项目
  4. ABP VNext学习日记24
  5. 心情不好的时候,就去做这5件事
  6. repo的入门和使用
  7. 土壤湿度传感器YL69使用
  8. 以IP地址的形式访问网站
  9. String简单介绍
  10. Snapchat正挑战Facebook统治地位 激战短消息