在Java中任何一个对象都有一个Monitor(可以认为是一个对象)与之关联,因为在Java的设计中 ,每一个Java对象被创建出来就带了一把看不见的锁,它叫做内部锁或者Monitor锁,也就是通常说Synchronized的对象锁,当且一个Monitor被持有后,它将处于锁定状态,监视器锁的实现依赖底层操作系统的Mutex互斥量(这是一种基于操作系统的重量级锁)。那么这个Monitor到底是什么?
在Hotspot中定义了一个ObjectMonitor结构:
ObjectMonitor::ObjectMonitor() {_header = NULL;_count = 0;_waiters = 0,_recursions = 0; //线程的重入次数_object = NULL;_owner = NULL; //标识拥有该monitor的线程_WaitSet = NULL; //处于wait状态的线程,会被加入到_WaitSet队列_WaitSetLock = 0 ;_Responsible = NULL ;_succ = NULL ;_cxq = NULL ; //维护着最新参与竞争的线程,也可以争夺锁资源FreeNext = NULL ;_EntryList = NULL ; //处于等待锁block状态的线程,会被加入到该列表,等待所释放争夺锁资源_SpinFreq = 0 ;_SpinClock = 0 ;OwnerIsThread = 0 ;}
_WaitSet:当获得Monitor的线程调用 wait() 方法,将释放当前持有的monitor,owner变量恢复为null,count自减1,同时将该线程封装成ObjectWaiter对象进入WaitSet 集合中等待被唤醒
_EntryList:Monitor已被其他线程获取,需要争夺锁的线程就进入_EntryList,等待锁释放再去争夺锁资源
_cxq:维护着最新参与竞争的线程,也可以争夺锁资源
enter()
通过该方法,开始获取重量级锁
- 如果当前Monitor的owner为null,通过CAS可直接获取
- 如果当前Monitor的owner是当前线程,则 _recursions 自增,记录重入次数
- 如果当前线程获取了轻量级锁,可以直接获取Monitor
- 如果Monitor对象已被获取,则尝试自旋获取锁资源
- 自旋获取锁失败,将当前线程状态设为 BLOCKED_ON_MONITOR_ENTER
- 进入 EnterI() 方法, 再次自旋获取锁
- 获取锁失败后,将对象封装为ObjectWaiter,CAS放入_cxq队列(放入失败再次自旋获取锁)
在阻塞前再次自旋获取锁,若失败后才阻塞线程 ```java void ATTR ObjectMonitor::enter(TRAPS) { //获取当前线程指针 Thread const Self = THREAD ; void cur ;
//CAS设置owner属性,如果_owner属性是NULL就将其设置为Self,否则返回当前的_owner属性 cur = Atomic::cmpxchg_ptr (Self, &_owner, NULL) ; if (cur == NULL) { //设置成功,说明该Monitor没有被人占用 assert (_recursions == 0 , “invariant”) ; assert (_owner == Self, “invariant”) ; // CONSIDER: set or assert OwnerIsThread == 1 return ; } //如果_owner就是当前线程 if (cur == Self) { //设置失败,说明该Monitor就是当前线程占用的,此处进入enter是嵌套加锁情形 _recursions ++ ; return ; }
//轻量级锁膨胀成重量级锁时,将owner设置为当前线程,直接返回 if (Self->is_lock_owned ((address)cur)) {
assert (_recursions == 0, “internal state error”); //正常轻量级膨胀成重量级锁时,之前已经获取轻量级锁的线程不需要二次调用enter方法 //此时再调用enter方法说明是锁嵌套情形,将_recursions置为1 _recursions = 1 ; //将owner置为当前线程 _owner = Self ; //表明当前线程是获取轻量级锁的 OwnerIsThread = 1 ; return ; }//该Monitor被其他某个线程占用了,需要抢占 assert (Self->_Stalled == 0, “invariant”) ; //记录需要抢占的Monitor指针 Self->_Stalled = intptr_t(this) ;
//Knob_SpinEarly默认为1,即为true //TrySpin让当前线程自旋,自旋的次数默认可以自适应调整,如果进入安全点同步则退出自旋,返回1表示抢占成功 if (Knob_SpinEarly && TrySpin (Self) > 0) { assert (_owner == Self , “invariant”) ; assert (_recursions == 0 , “invariant”) ; assert (((oop)(object()))->mark() == markOopDesc::encode(this), “invariant”) ; //将_Stalled置为NULL Self->_Stalled = 0 ; return ; }
//自旋若干次数后依然抢占失败 assert (_owner != Self , “invariant”) ; assert (_succ != Self , “invariant”) ; assert (Self->is_Java_thread() , “invariant”) ; JavaThread jt = (JavaThread ) Self ; //校验安全点同步未完成 assert (!SafepointSynchronize::is_at_safepoint(), “invariant”) ; assert (jt->thread_state() != _thread_blocked , “invariant”) ; assert (this->object() != NULL , “invariant”) ; assert (_count >= 0, “invariant”) ;
//原子的将_count属性加1,表示增加了一个抢占该锁的线程 Atomic::inc_ptr(&_count);
EventJavaMonitorEnter event;
{ //修改Java线程状态为BLOCKED_ON_MONITOR_ENTER,此代码块退出后还原成原来的 JavaThreadBlockedOnMonitorEnterState jtbmes(jt, this);
Self->set_current_pending_monitor(this);
DTRACE_MONITOR_PROBE(contended__enter, this, object(), jt); if (JvmtiExport::should_post_monitor_contended_enter()) { JvmtiExport::post_monitor_contended_enter(jt, this); }
//修改OS线程状态为MONITOR_WAIT,此代码块退出后还原成原来的 OSThreadContendState osts(Self->osthread()); //让当前线程的调用栈帧可以walkable,即可以被遍历,需要记录上一次执行的Java字节码 //然后切换线程的运行状态,从_thread_in_vm切换成_thread_blocked,切换的过程如果进入安全点同步则会被阻塞,此代码块退出将状态从_thread_blocked切换成_thread_in_vm,同样切换过程中如果进入安全点同步则被阻塞 ThreadBlockInVM tbivm(jt);
// TODO-FIXME: change the following for(;;) loop to straight-line code. for (;;) { //将线程的_suspend_equivalent属性置为true,该属性表明当前线程处于悬浮状态 jt->set_suspend_equivalent();
//会通过自旋,park等方式不断循环尝试获取锁,直到成功获取锁为止 EnterI (THREAD) ;
//ExitSuspendEquivalent默认返回false if (!ExitSuspendEquivalent(jt)) break ;
// 等待suspended当前线程的线程
_recursions = 0 ;
_succ = NULL ; exit (false, Self) ;
jt->java_suspend_self(); } //将关联的ObjectMonitor置为null,表示当前线程已经不在阻塞状态了 Self->set_current_pending_monitor(NULL); }
//原子的将count属性减1,表示已经有一个线程成功获取锁 Atomic::dec_ptr(&_count); assert (_count >= 0, “invariant”) ; Self->_Stalled = 0 ;
// Must either set _recursions = 0 or ASSERT _recursions == 0. assert (_recursions == 0 , “invariant”) ; assert (_owner == Self , “invariant”) ; assert (_succ != Self , “invariant”) ; assert (((oop)(object()))->mark() == markOopDesc::encode(this), “invariant”) ;
DTRACE_MONITOR_PROBE(contended__entered, this, object(), jt); if (JvmtiExport::should_post_monitor_contended_entered()) { JvmtiExport::post_monitor_contended_entered(jt, this); }
if (event.should_commit()) { event.set_klass(((oop)this->object())->klass()); event.set_previousOwner((TYPE_JAVALANGTHREAD)_previous_owner_tid); event.set_address((TYPE_ADDRESS)(uintptr_t)(this->object_addr())); event.commit(); }
if (ObjectMonitor::_sync_ContendedLockAttempts != NULL) { //增加计数 ObjectMonitor::_sync_ContendedLockAttempts->inc() ; } }
void ATTR ObjectMonitor::EnterI (TRAPS) { Thread Self = THREAD ; assert (Self->is_Java_thread(), “invariant”) ; //校验线程状态已经处于阻塞中 assert (((JavaThread ) Self)->thread_state() == _thread_blocked , “invariant”) ;
if (TryLock (Self) > 0) {//尝试获取锁,获取成功则返回assert (_succ != Self , "invariant") ;assert (_owner == Self , "invariant") ;assert (_Responsible != Self , "invariant") ;return ;}//初始化自旋相关配置参数DeferredInitialize () ;if (TrySpin (Self) > 0) {//再次尝试自旋,获取锁成功则返回assert (_owner == Self , "invariant") ;assert (_succ != Self , "invariant") ;assert (_Responsible != Self , "invariant") ;return ;}//自旋获取锁失败,将当前线程加入到等待队列中并且parkassert (_succ != Self , "invariant") ;assert (_owner != Self , "invariant") ;assert (_Responsible != Self , "invariant") ;//创建一个ObjectWaiter并初始化ObjectWaiter node(Self) ;Self->_ParkEvent->reset() ;node._prev = (ObjectWaiter *) 0xBAD ;node.TState = ObjectWaiter::TS_CXQ ;ObjectWaiter * nxt ;for (;;) {node._next = nxt = _cxq ;//原子的修改_cxq为node,如果修改成功则终止循环,表示已经成功加入到链表中if (Atomic::cmpxchg_ptr (&node, &_cxq, nxt) == nxt)break ;//修改失败,某个线程改变了cxqif (TryLock (Self) > 0) {//再次尝试获取锁,获取成功则返回assert (_succ != Self , "invariant") ;assert (_owner == Self , "invariant") ;assert (_Responsible != Self , "invariant") ;return ;}}//SyncFlags对的默认值是0if ((SyncFlags & 16) == 0 && nxt == NULL && _EntryList == NULL) {//nxt或者_EntryList为NULL,说明当前线程是第一个阻塞的线程,将_Responsible原子的修改为当前线程Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ;}TEVENT (Inflated enter - Contention) ;int nWakeups = 0 ;int RecheckInterval = 1 ;for (;;) {//尝试获取锁if (TryLock (Self) > 0) break ;assert (_owner != Self, "invariant") ;if ((SyncFlags & 2) && _Responsible == NULL) {//原子的将_Responsible置为SelfAtomic::cmpxchg_ptr (Self, &_Responsible, NULL) ;}//将目标线程park掉,底层通过操作系统的互斥量实现,让当前线程休眠if (_Responsible == Self || (SyncFlags & 1)) {TEVENT (Inflated enter - park TIMED) ;Self->_ParkEvent->park ((jlong) RecheckInterval) ;//增加等待时间,最大不超过1sRecheckInterval *= 8 ;if (RecheckInterval > 1000) RecheckInterval = 1000 ;} else {TEVENT (Inflated enter - park UNTIMED) ;Self->_ParkEvent->park() ;}//线程被唤醒了,即某个占用锁的线程释放了锁,尝试抢占该锁if (TryLock(Self) > 0)break ;TEVENT (Inflated enter - Futile wakeup) ;if (ObjectMonitor::_sync_FutileWakeups != NULL) {//增加计数ObjectMonitor::_sync_FutileWakeups->inc() ;}//增加计数++ nWakeups ;//Knob_SpinAfterFutile默认值是1,此时会再次尝试自旋获取锁if ((Knob_SpinAfterFutile & 1) && TrySpin (Self) > 0) break ;//Knob_ResetEvent默认值是0if ((Knob_ResetEvent & 1) && Self->_ParkEvent->fired()) {Self->_ParkEvent->reset() ;OrderAccess::fence() ;}if (_succ == Self) _succ = NULL ;//强制所有修改立即生效OrderAccess::fence() ;}//for循环结束,当前线程已经获取了锁assert (_owner == Self , "invariant") ;assert (object() != NULL , "invariant") ;//将其从EntryList或者cxq链表中移除UnlinkAfterAcquire (Self, &node) ;if (_succ == Self) _succ = NULL ;assert (_succ != Self, "invariant") ;if (_Responsible == Self) {//将_Responsible置为NULL_Responsible = NULL ;OrderAccess::fence(); // Dekker pivot-point}if (SyncFlags & 8) {OrderAccess::fence() ;}return ;
}
<a name="ZmgJ1"></a># exit()调用exit(),释放锁资源,让自旋状态的线程参与锁争夺或唤醒阻塞的线程1. 如果 _recursions 不为0,则说明有重入,只需将_recursions 自减并返回1. Knob_ExitPolicy == 0 (默认) 释放锁资源,此时处于自旋状态的线程可以获取锁,若_cxq/EntryList不为空,后续**再次抢占锁**,**若失败则说明自旋状态的线程抢锁成功**,直接返回。(该**策略保证自旋状态的线程优先获取锁**)1. Knob_ExitPolicy == 2 唤醒cxq队列中的线程并返回1. Knob_ExitPolicy == 3 拿出_cxq队列中的所有元素,逐个放到_EntryList队列的**尾部**,构成新的双向链表,把_cxq队列置为null1. Knob_ExitPolicy == 4 拿出_cxq队列中的所有元素,逐个放到_EntryList队列的**头部**,构成新的双向链表,并把_cxq队列置为null1. 如果_EntryList不为空,唤醒_EntryList中的线程,直接返回。1. _EntryList为空,若Knob_ExitPolicy == 1,将_cxq中的元素的顺序倒转,放入_EntryList中,构成新的双向链表。若Knob_ExitPolicy != 1,则说明是Knob_ExitPolicy ==0的时候释放锁失败(没有自旋线程抢锁,释放了锁有被当前线程抢回来),则之间把_cxq队列的元素放到_EntryList中1. 唤醒_EntryList中的线程```javavoid 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_ENTER,并构成一个双向链表for (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_ENTER,并构成一个双向链表for (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 ;}//如果_EntryList不为空w = _EntryList ;if (w != NULL) {//通过unpark唤醒w对应的线程,唤醒后会该线程会负责将w从EntryList链表中移除assert (w->TState == ObjectWaiter::TS_ENTER, "invariant") ;ExitEpilog (Self, w) ;return ;}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 ;}}}
wait()
- 检查中断状态,如果被中断则抛出异常,java_lang_InterruptedException()
- 封装ObjectWaiter对象,加入到_WaitSet中,并释放Monitor
- 再次检查中断状态和有无被notify,没有调用park方法将线程挂起
线程被唤醒,从_WaitSet中移除,再次争夺锁资源,抢到锁后wait方法退出。 ```java void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { Thread const Self = THREAD; JavaThread jt = (JavaThread *)THREAD; EventJavaMonitorWait event; // 检查中断状态 if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) { //抛出异常 THROW(vmSymbols::java_lang_InterruptedException()); return; } //关联线程 Self->_Stalled = intptr_t(this); jt->set_current_waiting_monitor(this); //新建节点 ObjectWaiter node(Self); node.TState = ObjectWaiter::TS_WAIT; Self->_ParkEvent->reset(); OrderAccess::fence(); // ST into Event; membar ; LD interrupted-flag //CAS自旋给WaitSet加锁 Thread::SpinAcquire(&_WaitSetLock, “WaitSet - add”); //加入WaitSet等待队列 AddWaiter(&node); //CAS自旋给WaitSet释放锁 Thread::SpinRelease(&_WaitSetLock);
intptr_t save = _recursions; // record the old recursion count _waiters++; // increment the number of waiters _recursions = 0; // 记录线程重入次数 //当前线程从监视器退出,MonitorExit exit(true, Self);
int ret = OS_OK; int WasNotified = 0; { // State transition wrappers OSThread* osthread = Self->osthread(); OSThreadWaitState osts(osthread, true); { ThreadBlockInVM 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
} else if (node._notified == 0) { //未被notify通知
if (millis <= 0) {Self->_ParkEvent->park(); //将线程挂起} else {ret = Self->_ParkEvent->park(millis); //挂起指定时间}
} // were we externally suspended while we were waiting? if (ExitSuspendEquivalent (jt)) {
// TODO-FIXME: add -- if succ == Self then succ = null.jt->java_suspend_self();
}
} // Exit thread safepoint: transition _thread_blocked -> _thread_in_vm
//双重加锁检查,如果已在WaitSet则从WaitSet移除 if (node.TState == ObjectWaiter::TS_WAIT) { Thread::SpinAcquire(&_WaitSetLock, “WaitSet - unlink”); if (node.TState == ObjectWaiter::TS_WAIT) {
//从队列移除DequeueSpecificWaiter(&node); // unlink from WaitSetnode.TState = ObjectWaiter::TS_RUN;
} Thread::SpinRelease(&_WaitSetLock); }
OrderAccess::loadload(); if (_succ == Self) _succ = NULL; WasNotified = node._notified; //如果处于被唤醒状态重新抢占锁 OrderAccess::fence(); Self->_Stalled = 0; ObjectWaiter::TStates v = node.TState; if (v == ObjectWaiter::TS_RUN) { enter(Self); } else { ReenterI(Self, &node); //重入 node.wait_reenter_end(this); } } // OSThreadWaitState()
jt->set_current_waiting_monitor(NULL); _recursions = save; // restore the old recursion count _waiters—; // decrement the number of waiters
}
<a name="h5yiu"></a># notify()根据不同的policy,对**_WaitSet中的头节**点进行不同操作进行不同1. policy = 0,将该节点放入 _EntryList头部。1. policy = 1,将该节点放入 _EntryList尾部。1. policy = 2,将该节点放入 _cqx头部。1. policy = 3,将该节点放入 _cqx尾部。1. policy = 4,直接将线程唤醒。```javavoid ObjectMonitor::INotify(Thread * Self) {const int policy = Knob_MoveNotifyee;//锁住队列Thread::SpinAcquire(&_WaitSetLock, "WaitSet - notify");//得到_WaitSet中第一个节点ObjectWaiter * iterator = DequeueWaiter();if (iterator != NULL) {if (policy != 4) { //将状态置为TS_ENTERiterator->TState = ObjectWaiter::TS_ENTER;}iterator->_notified = 1; //标记为被唤醒iterator->_notifier_tid = THREAD_TRACE_ID(Self);ObjectWaiter * list = _EntryList;if (policy == 0) { //放到EntryList头部if (list == NULL) {iterator->_next = iterator->_prev = NULL;_EntryList = iterator;} else {list->_prev = iterator;iterator->_next = list;iterator->_prev = NULL;_EntryList = iterator;}} else if (policy == 1) { //放到EntryList尾部if (list == NULL) {iterator->_next = iterator->_prev = NULL;_EntryList = iterator;} else {ObjectWaiter * tail;for (tail = list; tail->_next != NULL; tail = tail->_next) /* empty */;assert(tail != NULL && tail->_next == NULL, "invariant");tail->_next = iterator;iterator->_prev = tail;iterator->_next = NULL;}} else if (policy == 2) { // 放到cxq头部if (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;}}}} else if (policy == 3) { // 放到cxq尾部iterator->TState = ObjectWaiter::TS_CXQ;for (;;) {ObjectWaiter * 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 { //唤醒ParkEvent * ev = iterator->_event;iterator->TState = ObjectWaiter::TS_RUN;OrderAccess::fence();ev->unpark();}if (policy < 4) {//修改线程状态,记录锁竞争开始iterator->wait_reenter_begin(this);}}Thread::SpinRelease(&_WaitSetLock);}

锁的膨胀
上面这些方法只有重量级锁状态才能调用,如果当前对象非重量级锁调用了上述方法,会调用 inflate() 方法直接膨胀为重量级锁。
ObjectMonitor * ATTR ObjectSynchronizer::inflate (Thread * Self, oop object) {// Inflate mutates the heap ...// Relaxing assertion for bug 6320749.assert (Universe::verify_in_progress() ||!SafepointSynchronize::is_at_safepoint(), "invariant") ;for (;;) {//获取对象的 Mark Wordconst markOop mark = object->mark() ;//确保当前对象非偏向锁状态assert (!mark->has_bias_pattern(), "invariant") ;// The mark can be in one of the following states: 对象Mark Word有一下几种状态// * Inflated - just return 重量级锁状态// * Stack-locked - coerce it to inflated 轻量级锁状态// * INFLATING - busy wait for conversion to complete 正在膨胀为重量级锁中// * Neutral - aggressively inflate the object. 无锁状态// * BIASED - Illegal. We should never see this 偏向状态(在该方法中不允许出现)// CASE: inflated 当处于重量级锁状态,直接返回if (mark->has_monitor()) {ObjectMonitor * inf = mark->monitor() ;assert (inf->header()->is_neutral(), "invariant");assert (inf->object() == object, "invariant") ;assert (ObjectSynchronizer::verify_objmon_isinpool(inf), "monitor is invalid");return inf ;}// 处于膨胀中if (mark == markOopDesc::INFLATING()) {TEVENT (Inflate: spin while INFLATING) ;ReadStableMark(object) ;continue ;}// CASE: stack-locked 处于轻量级锁中if (mark->has_locker()) {ObjectMonitor * m = omAlloc (Self) ;m->Recycle();m->_Responsible = NULL ;m->OwnerIsThread = 0 ;m->_recursions = 0 ;m->_SpinDuration = ObjectMonitor::Knob_SpinLimit ; // Consider: maintain by type/classmarkOop cmp = (markOop) Atomic::cmpxchg_ptr (markOopDesc::INFLATING(), object->mark_addr(), mark) ;if (cmp != mark) {omRelease (Self, m, true) ;continue ; // Interference -- just retry}markOop dmw = mark->displaced_mark_helper() ;assert (dmw->is_neutral(), "invariant") ;// Setup monitor fields to proper values -- prepare the monitorm->set_header(dmw) ;m->set_owner(mark->locker());m->set_object(object);guarantee (object->mark() == markOopDesc::INFLATING(), "invariant") ;object->release_set_mark(markOopDesc::encode(m));if (ObjectMonitor::_sync_Inflations != NULL) ObjectMonitor::_sync_Inflations->inc() ;TEVENT(Inflate: overwrite stacklock) ;if (TraceMonitorInflation) {if (object->is_instance()) {ResourceMark rm;tty->print_cr("Inflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",(void *) object, (intptr_t) object->mark(),object->klass()->external_name());}}return m ;}// CASE: neutral 处于无锁状态assert (mark->is_neutral(), "invariant");ObjectMonitor * m = omAlloc (Self) ;// prepare m for installation - set monitor to initial statem->Recycle();m->set_header(mark);m->set_owner(NULL);m->set_object(object);m->OwnerIsThread = 1 ;m->_recursions = 0 ;m->_Responsible = NULL ;m->_SpinDuration = ObjectMonitor::Knob_SpinLimit ; // consider: keep metastats by type/classif (Atomic::cmpxchg_ptr (markOopDesc::encode(m), object->mark_addr(), mark) != mark) {m->set_object (NULL) ;m->set_owner (NULL) ;m->OwnerIsThread = 0 ;m->Recycle() ;omRelease (Self, m, true) ;m = NULL ;continue ;// interference - the markword changed - just retry.// The state-transitions are one-way, so there's no chance of// live-lock -- "Inflated" is an absorbing state.}if (ObjectMonitor::_sync_Inflations != NULL) ObjectMonitor::_sync_Inflations->inc() ;TEVENT(Inflate: overwrite neutral) ;if (TraceMonitorInflation) {if (object->is_instance()) {ResourceMark rm;tty->print_cr("Inflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",(void *) object, (intptr_t) object->mark(),object->klass()->external_name());}}return m ;}}
