现在来回答下之前提出的问题:为什么在撤销轻量级锁的时候会有失败的可能?
假设thread1拥有了轻量级锁,Mark Word指向thread1栈帧,thread2请求锁的时候,就会膨胀初始化ObjectMonitor对象,将Mark Word更新为指向ObjectMonitor的指针,那么在thread1退出的时候,CAS操作会失败,因为Mark Word不再指向thread1的栈帧,这个时候thread1自旋等待infalte完毕,执行重量级锁的退出操作
重量级锁的获取入口:
void ATTR ObjectMonitor::enter(TRAPS) { Thread * const Self = THREAD ; void * cur ; cur = Atomic::cmpxchg_ptr (Self, &_owner, NULL) ; if (cur == NULL) { assert (_recursions == 0 , "invariant") ; assert (_owner == Self, "invariant") ; return ; } if (cur == Self) { _recursions ++ ; return ; } if (Self->is_lock_owned ((address)cur)) { assert (_recursions == 0, "internal state error"); _recursions = 1 ; // Commute owner from a thread-specific on-stack BasicLockObject address to // a full-fledged "Thread *". _owner = Self ; OwnerIsThread = 1 ; return ; } /** *上述部分在前面已经分析过,不再累述 **/ Self->_Stalled = intptr_t(this) ; //TrySpin是一个自旋获取锁的操作,此处就不列出源码了 if (Knob_SpinEarly && TrySpin (Self) > 0) { Self->_Stalled = 0 ; return ; } /* *省略部分代码 */ for (;;) { EnterI (THREAD) ; /** *省略了部分代码 **/ } }进入EnterI (TRAPS)方法(这段代码个人觉得很有意思):
void ATTR ObjectMonitor::EnterI (TRAPS) { Thread * Self = THREAD ; if (TryLock (Self) > 0) { //这下不自旋了,我就默默的TryLock一下 return ; } DeferredInitialize () ; //此处又有自旋获取锁的操作 if (TrySpin (Self) > 0) { return ; } /** *到此,自旋终于全失败了,要入队挂起了 **/ ObjectWaiter node(Self) ; //将Thread封装成ObjectWaiter结点 Self->_ParkEvent->reset() ; node._prev = (ObjectWaiter *) 0xBAD ; node.TState = ObjectWaiter::TS_CXQ ; ObjectWaiter * nxt ; for (;;) { //循环,保证将node插入队列 node._next = nxt = _cxq ;//将node插入到_cxq队列的首部 //CAS修改_cxq指向node if (Atomic::cmpxchg_ptr (&node, &_cxq, nxt) == nxt) break ; if (TryLock (Self) > 0) {//我再默默的TryLock一下,真的是不想挂起呀! return ; } } if ((SyncFlags & 16) == 0 && nxt == NULL && _EntryList == NULL) { // Try to assume the role of responsible thread for the monitor. // CONSIDER: ST vs CAS vs { if (Responsible==null) Responsible=Self } Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ; } TEVENT (Inflated enter - Contention) ; int nWakeups = 0 ; int RecheckInterval = 1 ; for (;;) { if (TryLock (Self) > 0) break ;//临死之前,我再TryLock下 if ((SyncFlags & 2) && _Responsible == NULL) { Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ; } if (_Responsible == Self || (SyncFlags & 1)) { TEVENT (Inflated enter - park TIMED) ; Self->_ParkEvent->park ((jlong) RecheckInterval) ; RecheckInterval *= 8 ; if (RecheckInterval > 1000) RecheckInterval = 1000 ; } else { TEVENT (Inflated enter - park UNTIMED) ; Self->_ParkEvent->park() ; //终于挂起了 } if (TryLock(Self) > 0) break ; /** *后面代码省略 **/ }