wait/notify原理 - 图1

    • Owner线程发现条件不满足,调用wait方法,即可进入WaitSet编程WAITING状态;
    • BLOCKEDWAITING的线程都处于阻塞状态,不占用CPU时间片;
    • BLOCKED线程会在Owner线程释放锁唤醒;
    • WAITING线程会在Owner线程调用notifynotifyAll唤醒,但唤醒后并不意味着立刻获得锁,仍需进入EntryList重新竞争;


    C++原理

    1. void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
    2. // 创建线程
    3. Thread * const Self = THREAD ;
    4. // ...
    5. // 将线程放进node双向链表中
    6. ObjectWaiter node(Self);
    7. // 等待队列状态
    8. node.TState = ObjectWaiter::TS_WAIT ;
    9. Self->_ParkEvent->reset() ;
    10. // 中断标记
    11. OrderAccess::fence();
    12. // ...
    13. // 加入队列
    14. AddWaiter (&node) ;
    15. // 下面就是一些运行后方法,改变node的状态
    16. intptr_t save = _recursions; // record the old recursion count
    17. _waiters++; // 等待队列加值
    18. _recursions = 0; // 设置重入锁
    19. exit (true, Self) ; // 退出monitor
    20. guarantee (_owner != Self, "invariant") ;
    21. // 线程状态
    22. ObjectWaiter::TStates v = node.TState ;
    23. // 线程状态为运行态
    24. if (v == ObjectWaiter::TS_RUN) {
    25. enter (Self) ;
    26. } else {
    27. guarantee (v == ObjectWaiter::TS_ENTER || v == ObjectWaiter::TS_CXQ, "invariant") ;
    28. ReenterI (Self, &node) ;
    29. node.wait_reenter_end(this);
    30. }
    31. }
    32. inline void ObjectMonitor::AddWaiter(ObjectWaiter* node) {
    33. assert(node != NULL, "should not dequeue NULL node");
    34. assert(node->_prev == NULL, "node already in list");
    35. assert(node->_next == NULL, "node already in list");
    36. // 将节点放在队列末尾(循环双向链表)
    37. if (_WaitSet == NULL) {
    38. _WaitSet = node;
    39. node->_prev = node;
    40. node->_next = node;
    41. } else {
    42. ObjectWaiter* head = _WaitSet ;
    43. ObjectWaiter* tail = head->_prev;
    44. assert(tail->_next == head, "invariant check");
    45. tail->_next = node;
    46. head->_prev = node;
    47. node->_next = head;
    48. node->_prev = tail;
    49. }
    50. }
    51. //线程释放调用exit方法
    52. void ATTR ObjectMonitor::exit(bool not_suspended, TRAPS) {
    53. // 创建线程
    54. Thread * Self = THREAD ;
    55. // 线程不是所属者
    56. if (THREAD != _owner) {
    57. // 执行检查锁拥有者
    58. if (THREAD->is_lock_owned((address) _owner)) {
    59. // 将该线程设置给拥有者
    60. _owner = THREAD ;
    61. // 设置重入锁
    62. _recursions = 0 ;
    63. // 拥有者标记
    64. OwnerIsThread = 1 ;
    65. } else {
    66. // 抛出异常
    67. ...
    68. }
    69. //_recursions计数不等于0;说明还没出代码块;进入减减操作,
    70. if (_recursions != 0) {
    71. _recursions--; // this is simple recursive enter
    72. TEVENT (Inflated exit - recursive) ;
    73. return ;
    74. }
    75. if ((SyncFlags & 4) == 0) {
    76. _Responsible = NULL ;
    77. }
    78. ...
    79. // 计数为0;开始唤醒cq竞争队列、enteryList阻塞队列
    80. ObjectWaiter * w = NULL ;//w就是被唤醒的线程
    81. // qmode = 2:直接绕过EntryList阻塞队列,从cxq(竞争)队列中获取线程用于竞争锁
    82. if (QMode == 2 && _cxq != NULL) {
    83. w = _cxq ;
    84. ExitEpilog (Self, w) ;
    85. return ;
    86. }
    87. // qmode =3:从cxq(竞争)队列插入EntryList(阻塞)尾部;
    88. if (QMode == 3 && _cxq != NULL) {
    89. ...
    90. }
    91. // qmode =4:从cxq队列插入到_EntryList头部
    92. if (QMode == 4 && _cxq != NULL) {
    93. ...
    94. }
    95. }
    96. //唤醒线程
    97. void ObjectMonitor::ExitEpilog (Thread * Self, ObjectWaiter * Wakee) {
    98. ParkEvent * Trigger = Wakee->_event ;
    99. // 唤醒之前被park()挂起的线程.
    100. Trigger->unpark() ;// invoke ObjectMonitor::EnterI 方法,继续竞争
    101. if (ObjectMonitor::_sync_Parks != NULL) {
    102. ObjectMonitor::_sync_Parks->inc() ;
    103. }
    104. }
    105. // 如果锁是空(cxq == null && succ == null)
    106. // 并且在系统中并不是立即把线程从WaitSet移到EntryList
    107. // 我们只是会唤醒一些线程,通过unpark()做到
    108. void ObjectMonitor::notify(TRAPS) {
    109. // 任务调度器
    110. int Policy = Knob_MoveNotifyee ;
    111. }