在Java中任何一个对象都有一个Monitor(可以认为是一个对象)与之关联,因为在Java的设计中 ,每一个Java对象被创建出来就带了一把看不见的锁,它叫做内部锁或者Monitor锁,也就是通常说Synchronized的对象锁,当且一个Monitor被持有后,它将处于锁定状态,监视器锁的实现依赖底层操作系统的Mutex互斥量(这是一种基于操作系统的重量级锁)。那么这个Monitor到底是什么?

在Hotspot中定义了一个ObjectMonitor结构:

  1. ObjectMonitor::ObjectMonitor() {
  2. _header = NULL;
  3. _count = 0;
  4. _waiters = 0,
  5. _recursions = 0; //线程的重入次数
  6. _object = NULL;
  7. _owner = NULL; //标识拥有该monitor的线程
  8. _WaitSet = NULL; //处于wait状态的线程,会被加入到_WaitSet队列
  9. _WaitSetLock = 0 ;
  10. _Responsible = NULL ;
  11. _succ = NULL ;
  12. _cxq = NULL ; //维护着最新参与竞争的线程,也可以争夺锁资源
  13. FreeNext = NULL ;
  14. _EntryList = NULL ; //处于等待锁block状态的线程,会被加入到该列表,等待所释放争夺锁资源
  15. _SpinFreq = 0 ;
  16. _SpinClock = 0 ;
  17. OwnerIsThread = 0 ;
  18. }

_WaitSet:当获得Monitor的线程调用 wait() 方法,将释放当前持有的monitor,owner变量恢复为null,count自减1,同时将该线程封装成ObjectWaiter对象进入WaitSet 集合中等待被唤醒
_EntryList:Monitor已被其他线程获取,需要争夺锁的线程就进入_EntryList,等待锁释放再去争夺锁资源
_cxq:维护着最新参与竞争的线程,也可以争夺锁资源

enter()

通过该方法,开始获取重量级锁

  1. 如果当前Monitor的owner为null,通过CAS可直接获取
  2. 如果当前Monitor的owner是当前线程,则 _recursions 自增,记录重入次数
  3. 如果当前线程获取了轻量级锁,可以直接获取Monitor
  4. 如果Monitor对象已被获取,则尝试自旋获取锁资源
  5. 自旋获取锁失败,将当前线程状态设为 BLOCKED_ON_MONITOR_ENTER
  6. 进入 EnterI() 方法, 再次自旋获取锁
  7. 获取锁失败后,将对象封装为ObjectWaiter,CAS放入_cxq队列(放入失败再次自旋获取锁)
  8. 在阻塞前再次自旋获取锁,若失败后才阻塞线程 ```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当前线程的线程

    1. _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”) ;

  1. if (TryLock (Self) > 0) {
  2. //尝试获取锁,获取成功则返回
  3. assert (_succ != Self , "invariant") ;
  4. assert (_owner == Self , "invariant") ;
  5. assert (_Responsible != Self , "invariant") ;
  6. return ;
  7. }
  8. //初始化自旋相关配置参数
  9. DeferredInitialize () ;
  10. if (TrySpin (Self) > 0) {
  11. //再次尝试自旋,获取锁成功则返回
  12. assert (_owner == Self , "invariant") ;
  13. assert (_succ != Self , "invariant") ;
  14. assert (_Responsible != Self , "invariant") ;
  15. return ;
  16. }
  17. //自旋获取锁失败,将当前线程加入到等待队列中并且park
  18. assert (_succ != Self , "invariant") ;
  19. assert (_owner != Self , "invariant") ;
  20. assert (_Responsible != Self , "invariant") ;
  21. //创建一个ObjectWaiter并初始化
  22. ObjectWaiter node(Self) ;
  23. Self->_ParkEvent->reset() ;
  24. node._prev = (ObjectWaiter *) 0xBAD ;
  25. node.TState = ObjectWaiter::TS_CXQ ;
  26. ObjectWaiter * nxt ;
  27. for (;;) {
  28. node._next = nxt = _cxq ;
  29. //原子的修改_cxq为node,如果修改成功则终止循环,表示已经成功加入到链表中
  30. if (Atomic::cmpxchg_ptr (&node, &_cxq, nxt) == nxt)
  31. break ;
  32. //修改失败,某个线程改变了cxq
  33. if (TryLock (Self) > 0) {
  34. //再次尝试获取锁,获取成功则返回
  35. assert (_succ != Self , "invariant") ;
  36. assert (_owner == Self , "invariant") ;
  37. assert (_Responsible != Self , "invariant") ;
  38. return ;
  39. }
  40. }
  41. //SyncFlags对的默认值是0
  42. if ((SyncFlags & 16) == 0 && nxt == NULL && _EntryList == NULL) {
  43. //nxt或者_EntryList为NULL,说明当前线程是第一个阻塞的线程,将_Responsible原子的修改为当前线程
  44. Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ;
  45. }
  46. TEVENT (Inflated enter - Contention) ;
  47. int nWakeups = 0 ;
  48. int RecheckInterval = 1 ;
  49. for (;;) {
  50. //尝试获取锁
  51. if (TryLock (Self) > 0) break ;
  52. assert (_owner != Self, "invariant") ;
  53. if ((SyncFlags & 2) && _Responsible == NULL) {
  54. //原子的将_Responsible置为Self
  55. Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ;
  56. }
  57. //将目标线程park掉,底层通过操作系统的互斥量实现,让当前线程休眠
  58. if (_Responsible == Self || (SyncFlags & 1)) {
  59. TEVENT (Inflated enter - park TIMED) ;
  60. Self->_ParkEvent->park ((jlong) RecheckInterval) ;
  61. //增加等待时间,最大不超过1s
  62. RecheckInterval *= 8 ;
  63. if (RecheckInterval > 1000) RecheckInterval = 1000 ;
  64. } else {
  65. TEVENT (Inflated enter - park UNTIMED) ;
  66. Self->_ParkEvent->park() ;
  67. }
  68. //线程被唤醒了,即某个占用锁的线程释放了锁,尝试抢占该锁
  69. if (TryLock(Self) > 0)
  70. break ;
  71. TEVENT (Inflated enter - Futile wakeup) ;
  72. if (ObjectMonitor::_sync_FutileWakeups != NULL) {
  73. //增加计数
  74. ObjectMonitor::_sync_FutileWakeups->inc() ;
  75. }
  76. //增加计数
  77. ++ nWakeups ;
  78. //Knob_SpinAfterFutile默认值是1,此时会再次尝试自旋获取锁
  79. if ((Knob_SpinAfterFutile & 1) && TrySpin (Self) > 0) break ;
  80. //Knob_ResetEvent默认值是0
  81. if ((Knob_ResetEvent & 1) && Self->_ParkEvent->fired()) {
  82. Self->_ParkEvent->reset() ;
  83. OrderAccess::fence() ;
  84. }
  85. if (_succ == Self) _succ = NULL ;
  86. //强制所有修改立即生效
  87. OrderAccess::fence() ;
  88. }
  89. //for循环结束,当前线程已经获取了锁
  90. assert (_owner == Self , "invariant") ;
  91. assert (object() != NULL , "invariant") ;
  92. //将其从EntryList或者cxq链表中移除
  93. UnlinkAfterAcquire (Self, &node) ;
  94. if (_succ == Self) _succ = NULL ;
  95. assert (_succ != Self, "invariant") ;
  96. if (_Responsible == Self) {
  97. //将_Responsible置为NULL
  98. _Responsible = NULL ;
  99. OrderAccess::fence(); // Dekker pivot-point
  100. }
  101. if (SyncFlags & 8) {
  102. OrderAccess::fence() ;
  103. }
  104. return ;

}

  1. <a name="ZmgJ1"></a>
  2. # exit()
  3. 调用exit(),释放锁资源,让自旋状态的线程参与锁争夺或唤醒阻塞的线程
  4. 1. 如果 _recursions 不为0,则说明有重入,只需将_recursions 自减并返回
  5. 1. Knob_ExitPolicy == 0 (默认) 释放锁资源,此时处于自旋状态的线程可以获取锁,若_cxq/EntryList不为空,后续**再次抢占锁**,**若失败则说明自旋状态的线程抢锁成功**,直接返回。(该**策略保证自旋状态的线程优先获取锁**)
  6. 1. Knob_ExitPolicy == 2 唤醒cxq队列中的线程并返回
  7. 1. Knob_ExitPolicy == 3 拿出_cxq队列中的所有元素,逐个放到_EntryList队列的**尾部**,构成新的双向链表,把_cxq队列置为null
  8. 1. Knob_ExitPolicy == 4 拿出_cxq队列中的所有元素,逐个放到_EntryList队列的**头部**,构成新的双向链表,并把_cxq队列置为null
  9. 1. 如果_EntryList不为空,唤醒_EntryList中的线程,直接返回。
  10. 1. _EntryList为空,若Knob_ExitPolicy == 1,将_cxq中的元素的顺序倒转,放入_EntryList中,构成新的双向链表。若Knob_ExitPolicy != 1,则说明是Knob_ExitPolicy ==0的时候释放锁失败(没有自旋线程抢锁,释放了锁有被当前线程抢回来),则之间把_cxq队列的元素放到_EntryList中
  11. 1. 唤醒_EntryList中的线程
  12. ```java
  13. void ATTR ObjectMonitor::exit(bool not_suspended, TRAPS) {
  14. Thread * Self = THREAD ;
  15. if (THREAD != _owner) {
  16. if (THREAD->is_lock_owned((address) _owner)) {
  17. //如果owner位于当前线程调用栈帧,说明该锁是轻量级锁膨胀来的
  18. assert (_recursions == 0, "invariant") ;
  19. //修改owner属性
  20. _owner = THREAD ;
  21. _recursions = 0 ;
  22. OwnerIsThread = 1 ;
  23. } else {
  24. //其他线程占用该锁,直接返回
  25. TEVENT (Exit - Throw IMSX) ;
  26. assert(false, "Non-balanced monitor enter/exit!");
  27. if (false) {
  28. THROW(vmSymbols::java_lang_IllegalMonitorStateException());
  29. }
  30. return;
  31. }
  32. }
  33. if (_recursions != 0) {
  34. //不等于0说明是嵌套加锁,将_recursions减1即可返回
  35. _recursions--; // this is simple recursive enter
  36. TEVENT (Inflated exit - recursive) ;
  37. return ;
  38. }
  39. // SyncFlags默认值是0
  40. if ((SyncFlags & 4) == 0) {
  41. _Responsible = NULL ;
  42. }
  43. for (;;) {
  44. assert (THREAD == _owner, "invariant") ;
  45. //Knob_ExitPolicy默认值是0
  46. if (Knob_ExitPolicy == 0) {
  47. //将_owner属性置为NULL,释放锁,如果某个线程正在自旋抢占该锁,则会抢占成功
  48. //即这种策略会优先保证通过自旋抢占锁的线程获取锁,而其他处于等待队列中的线程则靠后
  49. OrderAccess::release_store_ptr (&_owner, NULL) ; // drop the lock
  50. //让修改立即生效
  51. OrderAccess::storeload() ; // See if we need to wake a successor
  52. if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
  53. //如果_EntryList或者cxq链表是空的,则直接返回
  54. TEVENT (Inflated exit - simple egress) ;
  55. return ;
  56. }
  57. TEVENT (Inflated exit - complex egress) ;
  58. //如果_EntryList或者cxq链表不是空的,则原子的设置owner属性为当前线程,尝试抢占锁
  59. if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
  60. //抢占失败则返回,等占用该锁的线程释放后再处理链表中的等待线程
  61. return ;
  62. }
  63. TEVENT (Exit - Reacquired) ;
  64. } else {
  65. if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
  66. OrderAccess::release_store_ptr (&_owner, NULL) ; // drop the lock
  67. OrderAccess::storeload() ;
  68. // Ratify the previously observed values.
  69. if (_cxq == NULL || _succ != NULL) {
  70. TEVENT (Inflated exit - simple egress) ;
  71. return ;
  72. }
  73. //有可能cxq插入了一个新节点,导致上面的if不成立,需要重新获取锁
  74. if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
  75. TEVENT (Inflated exit - reacquired succeeded) ;
  76. return ;
  77. }
  78. TEVENT (Inflated exit - reacquired failed) ;
  79. } else {
  80. //如果_EntryList或者cxq链表不是空的则不释放锁,避免二次抢占锁,即优先处理等待队列中的线程
  81. TEVENT (Inflated exit - complex egress) ;
  82. }
  83. }
  84. guarantee (_owner == THREAD, "invariant") ;
  85. ObjectWaiter * w = NULL ;
  86. //Knob_QMode的默认值是0
  87. int QMode = Knob_QMode ;
  88. if (QMode == 2 && _cxq != NULL) {
  89. w = _cxq ;
  90. assert (w != NULL, "invariant") ;
  91. assert (w->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
  92. //通过unpark唤醒cxq对应的线程,唤醒后会将cxq从链表中移除
  93. ExitEpilog (Self, w) ;
  94. return ;
  95. }
  96. if (QMode == 3 && _cxq != NULL) {
  97. //将cxq链表中的元素插入到_EntryList链表的末尾
  98. w = _cxq ;
  99. for (;;) {
  100. assert (w != NULL, "Invariant") ;
  101. //将_cxq原子的置为NULL,如果失败则更新w,重新尝试直到成功为止
  102. //置为NULL后,如果有新的节点插入进来就形成了一个新的cxq链表
  103. ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
  104. if (u == w) break ;
  105. w = u ;
  106. }
  107. assert (w != NULL , "invariant") ;
  108. ObjectWaiter * q = NULL ;
  109. ObjectWaiter * p ;
  110. //遍历cxq中的所有节点,将其置为TS_ENTER,并构成一个双向链表
  111. for (p = w ; p != NULL ; p = p->_next) {
  112. guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
  113. p->TState = ObjectWaiter::TS_ENTER ;
  114. p->_prev = q ;
  115. q = p ;
  116. }
  117. ObjectWaiter * Tail ;
  118. //遍历_EntryList找到末尾元素,将w插入到后面
  119. for (Tail = _EntryList ; Tail != NULL && Tail->_next != NULL ; Tail = Tail->_next) ;
  120. if (Tail == NULL) {
  121. _EntryList = w ;
  122. } else {
  123. Tail->_next = w ;
  124. w->_prev = Tail ;
  125. }
  126. }
  127. if (QMode == 4 && _cxq != NULL) {
  128. //将cxq链表中的元素插入到_EntryList链表的头部
  129. w = _cxq ;
  130. for (;;) {
  131. assert (w != NULL, "Invariant") ;
  132. //将_cxq原子的置为NULL,如果失败则更新w,重新尝试直到成功为止
  133. ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
  134. if (u == w) break ;
  135. w = u ;
  136. }
  137. assert (w != NULL , "invariant") ;
  138. ObjectWaiter * q = NULL ;
  139. ObjectWaiter * p ;
  140. //遍历cxq中的所有节点,将其置为TS_ENTER,并构成一个双向链表
  141. for (p = w ; p != NULL ; p = p->_next) {
  142. guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
  143. p->TState = ObjectWaiter::TS_ENTER ;
  144. //构成双向链表
  145. p->_prev = q ;
  146. q = p ;
  147. }
  148. //插入到_EntryList的头部
  149. if (_EntryList != NULL) {
  150. q->_next = _EntryList ;
  151. _EntryList->_prev = q ;
  152. }
  153. _EntryList = w ;
  154. }
  155. //如果_EntryList不为空
  156. w = _EntryList ;
  157. if (w != NULL) {
  158. //通过unpark唤醒w对应的线程,唤醒后会该线程会负责将w从EntryList链表中移除
  159. assert (w->TState == ObjectWaiter::TS_ENTER, "invariant") ;
  160. ExitEpilog (Self, w) ;
  161. return ;
  162. }
  163. w = _cxq ;
  164. if (w == NULL) continue ;//如果cxq为空则重新循环,不会进入此分支
  165. //cxq不为NULL
  166. for (;;) {
  167. assert (w != NULL, "Invariant") ;
  168. //将cxq原子的修改为NULL
  169. ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;
  170. if (u == w) break ;
  171. w = u ;
  172. }
  173. TEVENT (Inflated exit - drain cxq into EntryList) ;
  174. assert (w != NULL , "invariant") ;
  175. assert (_EntryList == NULL , "invariant") ;
  176. if (QMode == 1) {
  177. //遍历cxq中的元素将其加入到_EntryList中,注意顺序跟cxq中是反的
  178. ObjectWaiter * s = NULL ;
  179. ObjectWaiter * t = w ;
  180. ObjectWaiter * u = NULL ;
  181. while (t != NULL) {
  182. guarantee (t->TState == ObjectWaiter::TS_CXQ, "invariant") ;
  183. t->TState = ObjectWaiter::TS_ENTER ;
  184. u = t->_next ;
  185. t->_prev = u ;
  186. t->_next = s ;
  187. s = t;
  188. t = u ;
  189. }
  190. _EntryList = s ;
  191. assert (s != NULL, "invariant") ;
  192. } else {
  193. // QMode == 0 or QMode == 2
  194. //遍历cxq中的元素将其加入到_EntryList中,注意此时cxq链表的头元素被赋值给EntryList
  195. _EntryList = w ;
  196. ObjectWaiter * q = NULL ;
  197. ObjectWaiter * p ;
  198. //cxq中的元素是通过next属性串联起来的,prev属性没有,此处遍历加上prev属性
  199. //当EntryList头元素被移除了是取next属性作为EntryList
  200. for (p = w ; p != NULL ; p = p->_next) {
  201. guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ;
  202. p->TState = ObjectWaiter::TS_ENTER ;
  203. p->_prev = q ;
  204. q = p ;
  205. }
  206. }
  207. if (_succ != NULL) continue;
  208. w = _EntryList ;
  209. if (w != NULL) {
  210. guarantee (w->TState == ObjectWaiter::TS_ENTER, "invariant") ;
  211. //唤醒w对应的线程
  212. ExitEpilog (Self, w) ;
  213. return ;
  214. }
  215. }
  216. }

wait()

  1. 检查中断状态,如果被中断则抛出异常,java_lang_InterruptedException()
  2. 封装ObjectWaiter对象,加入到_WaitSet中,并释放Monitor
  3. 再次检查中断状态和有无被notify,没有调用park方法将线程挂起
  4. 线程被唤醒,从_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)) {

    1. // Intentionally empty

    } else if (node._notified == 0) { //未被notify通知

    1. if (millis <= 0) {
    2. Self->_ParkEvent->park(); //将线程挂起
    3. } else {
    4. ret = Self->_ParkEvent->park(millis); //挂起指定时间
    5. }

    } // were we externally suspended while we were waiting? if (ExitSuspendEquivalent (jt)) {

    1. // TODO-FIXME: add -- if succ == Self then succ = null.
    2. 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) {

    1. //从队列移除
    2. DequeueSpecificWaiter(&node); // unlink from WaitSet
    3. node.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

}

  1. <a name="h5yiu"></a>
  2. # notify()
  3. 根据不同的policy,对**_WaitSet中的头节**点进行不同操作进行不同
  4. 1. policy = 0,将该节点放入 _EntryList头部。
  5. 1. policy = 1,将该节点放入 _EntryList尾部。
  6. 1. policy = 2,将该节点放入 _cqx头部。
  7. 1. policy = 3,将该节点放入 _cqx尾部。
  8. 1. policy = 4,直接将线程唤醒。
  9. ```java
  10. void ObjectMonitor::INotify(Thread * Self) {
  11. const int policy = Knob_MoveNotifyee;
  12. //锁住队列
  13. Thread::SpinAcquire(&_WaitSetLock, "WaitSet - notify");
  14. //得到_WaitSet中第一个节点
  15. ObjectWaiter * iterator = DequeueWaiter();
  16. if (iterator != NULL) {
  17. if (policy != 4) { //将状态置为TS_ENTER
  18. iterator->TState = ObjectWaiter::TS_ENTER;
  19. }
  20. iterator->_notified = 1; //标记为被唤醒
  21. iterator->_notifier_tid = THREAD_TRACE_ID(Self);
  22. ObjectWaiter * list = _EntryList;
  23. if (policy == 0) { //放到EntryList头部
  24. if (list == NULL) {
  25. iterator->_next = iterator->_prev = NULL;
  26. _EntryList = iterator;
  27. } else {
  28. list->_prev = iterator;
  29. iterator->_next = list;
  30. iterator->_prev = NULL;
  31. _EntryList = iterator;
  32. }
  33. } else if (policy == 1) { //放到EntryList尾部
  34. if (list == NULL) {
  35. iterator->_next = iterator->_prev = NULL;
  36. _EntryList = iterator;
  37. } else {
  38. ObjectWaiter * tail;
  39. for (tail = list; tail->_next != NULL; tail = tail->_next) /* empty */;
  40. assert(tail != NULL && tail->_next == NULL, "invariant");
  41. tail->_next = iterator;
  42. iterator->_prev = tail;
  43. iterator->_next = NULL;
  44. }
  45. } else if (policy == 2) { // 放到cxq头部
  46. if (list == NULL) {
  47. iterator->_next = iterator->_prev = NULL;
  48. _EntryList = iterator;
  49. } else {
  50. iterator->TState = ObjectWaiter::TS_CXQ;
  51. for (;;) {
  52. ObjectWaiter * front = _cxq;
  53. iterator->_next = front;
  54. if (Atomic::cmpxchg_ptr(iterator, &_cxq, front) == front) {
  55. break;
  56. }
  57. }
  58. }
  59. } else if (policy == 3) { // 放到cxq尾部
  60. iterator->TState = ObjectWaiter::TS_CXQ;
  61. for (;;) {
  62. ObjectWaiter * tail = _cxq;
  63. if (tail == NULL) {
  64. iterator->_next = NULL;
  65. if (Atomic::cmpxchg_ptr(iterator, &_cxq, NULL) == NULL) {
  66. break;
  67. }
  68. } else {
  69. while (tail->_next != NULL) tail = tail->_next;
  70. tail->_next = iterator;
  71. iterator->_prev = tail;
  72. iterator->_next = NULL;
  73. break;
  74. }
  75. }
  76. } else { //唤醒
  77. ParkEvent * ev = iterator->_event;
  78. iterator->TState = ObjectWaiter::TS_RUN;
  79. OrderAccess::fence();
  80. ev->unpark();
  81. }
  82. if (policy < 4) {
  83. //修改线程状态,记录锁竞争开始
  84. iterator->wait_reenter_begin(this);
  85. }
  86. }
  87. Thread::SpinRelease(&_WaitSetLock);
  88. }

微信截图_20210630110144.png

锁的膨胀

上面这些方法只有重量级锁状态才能调用,如果当前对象非重量级锁调用了上述方法,会调用 inflate() 方法直接膨胀为重量级锁。

  1. ObjectMonitor * ATTR ObjectSynchronizer::inflate (Thread * Self, oop object) {
  2. // Inflate mutates the heap ...
  3. // Relaxing assertion for bug 6320749.
  4. assert (Universe::verify_in_progress() ||
  5. !SafepointSynchronize::is_at_safepoint(), "invariant") ;
  6. for (;;) {
  7. //获取对象的 Mark Word
  8. const markOop mark = object->mark() ;
  9. //确保当前对象非偏向锁状态
  10. assert (!mark->has_bias_pattern(), "invariant") ;
  11. // The mark can be in one of the following states: 对象Mark Word有一下几种状态
  12. // * Inflated - just return 重量级锁状态
  13. // * Stack-locked - coerce it to inflated 轻量级锁状态
  14. // * INFLATING - busy wait for conversion to complete 正在膨胀为重量级锁中
  15. // * Neutral - aggressively inflate the object. 无锁状态
  16. // * BIASED - Illegal. We should never see this 偏向状态(在该方法中不允许出现)
  17. // CASE: inflated 当处于重量级锁状态,直接返回
  18. if (mark->has_monitor()) {
  19. ObjectMonitor * inf = mark->monitor() ;
  20. assert (inf->header()->is_neutral(), "invariant");
  21. assert (inf->object() == object, "invariant") ;
  22. assert (ObjectSynchronizer::verify_objmon_isinpool(inf), "monitor is invalid");
  23. return inf ;
  24. }
  25. // 处于膨胀中
  26. if (mark == markOopDesc::INFLATING()) {
  27. TEVENT (Inflate: spin while INFLATING) ;
  28. ReadStableMark(object) ;
  29. continue ;
  30. }
  31. // CASE: stack-locked 处于轻量级锁中
  32. if (mark->has_locker()) {
  33. ObjectMonitor * m = omAlloc (Self) ;
  34. m->Recycle();
  35. m->_Responsible = NULL ;
  36. m->OwnerIsThread = 0 ;
  37. m->_recursions = 0 ;
  38. m->_SpinDuration = ObjectMonitor::Knob_SpinLimit ; // Consider: maintain by type/class
  39. markOop cmp = (markOop) Atomic::cmpxchg_ptr (markOopDesc::INFLATING(), object->mark_addr(), mark) ;
  40. if (cmp != mark) {
  41. omRelease (Self, m, true) ;
  42. continue ; // Interference -- just retry
  43. }
  44. markOop dmw = mark->displaced_mark_helper() ;
  45. assert (dmw->is_neutral(), "invariant") ;
  46. // Setup monitor fields to proper values -- prepare the monitor
  47. m->set_header(dmw) ;
  48. m->set_owner(mark->locker());
  49. m->set_object(object);
  50. guarantee (object->mark() == markOopDesc::INFLATING(), "invariant") ;
  51. object->release_set_mark(markOopDesc::encode(m));
  52. if (ObjectMonitor::_sync_Inflations != NULL) ObjectMonitor::_sync_Inflations->inc() ;
  53. TEVENT(Inflate: overwrite stacklock) ;
  54. if (TraceMonitorInflation) {
  55. if (object->is_instance()) {
  56. ResourceMark rm;
  57. tty->print_cr("Inflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
  58. (void *) object, (intptr_t) object->mark(),
  59. object->klass()->external_name());
  60. }
  61. }
  62. return m ;
  63. }
  64. // CASE: neutral 处于无锁状态
  65. assert (mark->is_neutral(), "invariant");
  66. ObjectMonitor * m = omAlloc (Self) ;
  67. // prepare m for installation - set monitor to initial state
  68. m->Recycle();
  69. m->set_header(mark);
  70. m->set_owner(NULL);
  71. m->set_object(object);
  72. m->OwnerIsThread = 1 ;
  73. m->_recursions = 0 ;
  74. m->_Responsible = NULL ;
  75. m->_SpinDuration = ObjectMonitor::Knob_SpinLimit ; // consider: keep metastats by type/class
  76. if (Atomic::cmpxchg_ptr (markOopDesc::encode(m), object->mark_addr(), mark) != mark) {
  77. m->set_object (NULL) ;
  78. m->set_owner (NULL) ;
  79. m->OwnerIsThread = 0 ;
  80. m->Recycle() ;
  81. omRelease (Self, m, true) ;
  82. m = NULL ;
  83. continue ;
  84. // interference - the markword changed - just retry.
  85. // The state-transitions are one-way, so there's no chance of
  86. // live-lock -- "Inflated" is an absorbing state.
  87. }
  88. if (ObjectMonitor::_sync_Inflations != NULL) ObjectMonitor::_sync_Inflations->inc() ;
  89. TEVENT(Inflate: overwrite neutral) ;
  90. if (TraceMonitorInflation) {
  91. if (object->is_instance()) {
  92. ResourceMark rm;
  93. tty->print_cr("Inflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
  94. (void *) object, (intptr_t) object->mark(),
  95. object->klass()->external_name());
  96. }
  97. }
  98. return m ;
  99. }
  100. }