/** * 线程等待 * @param var1 毫秒 * @param var3 纳秒 */ public final void wait(long var1, int var3) throws InterruptedException { if (var1 < 0L) { throw new IllegalArgumentException("timeout value is negative"); } else if (var3 >= 0 && var3 <= 999999) { //纳秒>0,毫秒直接++ if (var3 > 0) { ++var1; } //调用native方法 this.wait(var1); } else { throw new IllegalArgumentException("nanosecond timeout value out of range"); } } /** * native方法线程等待 */ public final native void wait(long var1) throws InterruptedException; /** * native方法线程单个唤醒 */ public final native void notify(); /** * native方法线程唤醒等待池中所有线程 */ public final native void notifyAll();
解析源码之前的先具备的条件:
对象锁ObjectMonitor拥有等待队列和同步队列两种队列
线程等待,让出对象锁,加入等待队列,然后进入park,等待其他线程释放锁unpark
synchronized (a) { a.wait(); }
等价于
moniter.enter //获取对象锁 { 1.判断锁是否存在 2.判断中断状态 3.创建node 加入 等待队列 4.moniter.exit(根据不同策略,从同步队列获取头节点线程a,然后执行线程a的event.unpark 唤醒机制) 5.本线程执行event.park 等待其他线程唤醒 6.判断唤醒是不是被中断唤醒的,需不需要抛出异常 } moniter.exit //释放锁,唤醒同步队列下一个对象
#define CHECK_OWNER() do { if (THREAD != _owner) { if (THREAD->is_lock_owned((address) _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)
//调用is_interrupted()判断并清除线程中断状态,如果中断状态为true,抛出中断异常并结束 if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) { ... TEVENT (Wait - Throw IEX) ; THROW(vmSymbols::java_lang_InterruptedException()); return ; }
Thread::SpinAcquire (&_WaitSetLock, "WaitSet - add") AddWaiter (&node) Thread::SpinRelease (&_WaitSetLock)
intptr_t save = _recursions; // 记录旧的递归次数 _waiters++; // waiters 自增 _recursions = 0; // 设置 recursion level to be 1 exit (Self) ; // 退出监视器
if (millis <= 0) { // 调用park()方法阻塞线程 Self->_ParkEvent->park () ; } else { // 调用park()方法在超时时间内阻塞线程 ret = Self->_ParkEvent->park (millis) ; }
if (!WasNotified) { if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) { TEVENT (Wait - throw IEX from epilog) ; THROW(vmSymbols::java_lang_InterruptedException()); } }
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 () ; // Throw IMSX or IEX. CHECK_OWNER(); //调用is_interrupted()判断并清除线程中断状态,如果中断状态为true,抛出中断异常并结束 if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) { //post monitor waited event //注意这是过去式,已经等待完了 if (JvmtiExport::should_post_monitor_waited()) { //注意:这里传递参数'false',这是因为由于线程中断,等待不会超时 JvmtiExport::post_monitor_waited(jt, this, false); } TEVENT (Wait - Throw IEX) ; THROW(vmSymbols::java_lang_InterruptedException()); return ; } TEVENT (Wait) ; assert (Self->_Stalled == 0, "invariant") ; Self->_Stalled = intptr_t(this) ; jt->set_current_waiting_monitor(this); // create a node to be put into the queue // Critically, after we reset() the event but prior to park(), we must check // for a pending interrupt. //创建一个node放入队列 //关键是,在reset()之后,但在park()之前,必须检查是否有挂起的中断 ObjectWaiter node(Self); node.TState = ObjectWaiter::TS_WAIT ; Self->_ParkEvent->reset() ; OrderAccess::fence(); //在本例中等待队列是一个循环的双向链表,但它也可以是一个优先级队列或任何数据结构。 //_WaitSetLock保护着等待队列. //通常,等待队列只能由监视器*except*的所有者访问,但在park()因中断超时而返回的情况下也是可以。 //竞争非常小,所以使用一个自旋锁而不是重量级的阻塞锁。 Thread::SpinAcquire (&_WaitSetLock, "WaitSet - add") ; AddWaiter (&node) ; Thread::SpinRelease (&_WaitSetLock) ; if ((SyncFlags & 4) == 0) { _Responsible = NULL ; } intptr_t save = _recursions; // 记录旧的递归次数 _waiters++; // waiters 自增 _recursions = 0; // 设置 recursion level to be 1 exit (Self) ; // 退出监视器 guarantee (_owner != Self, "invariant") ; //一旦在上面的exit()调用中删除了ObjectMonitor的所有权, //另一个线程就可以进入ObjectMonitor,执行notify()和exit()对象监视器。 //如果另一个线程的exit()调用选择此线程作为后继者,并且此线程在发布MONITOR_CONTENDED_EXIT时发生unpark()调用, //则我们使用RawMonitors运行事件风险处理,并使用unpark(). //为了避免这个问题,我们重新发布事件,即使未使用原来的unpark(), //这也不会造成任何伤害,因为已经为此监视器选好了继任者。 if (node._notified != 0 && _succ == Self) { node._event->unpark(); } // The thread is on the WaitSet list - now park() it. // On MP systems it's conceivable that a brief spin before we park // could be profitable. // // 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 wrappers OSThread* osthread = Self->osthread(); OSThreadWaitState osts(osthread, true); { ThreadBlockInVM tbivm(jt); // Thread is in thread_blocked state and oop access is unsafe. //线程处于阻塞状态,并且oop访问是不安全的 jt->set_suspend_equivalent(); if (interruptible && (Thread::is_interrupted(THREAD, false) || HAS_PENDING_EXCEPTION)) { // Intentionally empty 空处理 } else if (node._notified == 0) { if (millis <= 0) { // 调用park()方法阻塞线程 Self->_ParkEvent->park () ; } else { // 调用park()方法在超时时间内阻塞线程 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 //当线程不在等待队列时,使用双重检查锁定避免获取_WaitSetLock if (node.TState == ObjectWaiter::TS_WAIT) { Thread::SpinAcquire (&_WaitSetLock, "WaitSet - unlink") ; if (node.TState == ObjectWaiter::TS_WAIT) { DequeueSpecificWaiter (&node) ; // unlink from WaitSet assert(node._notified == 0, "invariant"); node.TState = ObjectWaiter::TS_RUN ; } Thread::SpinRelease (&_WaitSetLock) ; } //从这个线程的角度来看,Node's TState是稳定的, //没有其他线程能够异步修改TState guarantee (node.TState != ObjectWaiter::TS_WAIT, "invariant") ; OrderAccess::loadload() ; if (_succ == Self) _succ = NULL ; WasNotified = node._notified ; // Reentry phase -- reacquire the monitor. // re-enter contended(竞争) monitor after object.wait(). // retain OBJECT_WAIT state until re-enter successfully completes // Thread state is thread_in_vm and oop access is again safe, // although the raw address of the object may have changed. // (Don't cache naked oops over safepoints, of course). // post monitor waited event. //注意这是过去式,已经等待完了 if (JvmtiExport::should_post_monitor_waited()) { JvmtiExport::post_monitor_waited(jt, this, 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 { guarantee (v == ObjectWaiter::TS_ENTER || v == ObjectWaiter::TS_CXQ, "invariant") ; ReenterI (Self, &node) ; node.wait_reenter_end(this); } // Self has reacquired the lock. // Lifecycle - the node representing Self must not appear on any queues. // Node is about to go out-of-scope, but even if it were immortal(长久的) we wouldn't // want residual(残留的) elements associated with this thread left on any lists. 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 postconditions assert (_owner == Self , "invariant") ; assert (_succ != Self , "invariant") ; assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ; if (SyncFlags & 32) { OrderAccess::fence() ; } //检查是否有通知notify发生 // 从park()方法返回后,判断是否是因为中断返回,再次调用 // thread::is_interrupted(Self, true)判断并清除线程中断状态 // 如果中断状态为true,抛出中断异常并结束。 if (!WasNotified) { // no, it could be timeout or Thread.interrupt() or both // check for interrupt event, otherwise it is timeout if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) { TEVENT (Wait - throw IEX from epilog) ; THROW(vmSymbols::java_lang_InterruptedException()); } } //注意:虚假唤醒将被视为超时;监视器通知优先于线程中断。 }
synchronized (a) { a.notify(); }
相当于
moniter.enter //获取对象锁 { 1.判断锁是否存在 2.从等待队列中获取第一个节点 3.根据不同的policy策略加入到cxq 或者entryList 同步队列 } moniter.exit //释放锁,唤醒同步队列下一个对象
#define CHECK_OWNER() do { if (THREAD != _owner) { if (THREAD->is_lock_owned((address) _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)
ObjectWaiter * iterator = DequeueWaiter() ;
if (Policy == 0) { // prepend(预追加) to EntryList if (List == NULL) { iterator->_next = iterator->_prev = NULL ; _EntryList = iterator ; } else { List->_prev = iterator ; iterator->_next = List ; iterator->_prev = NULL ; _EntryList = iterator ; } }......
void ObjectMonitor::notify(TRAPS) { CHECK_OWNER(); if (_WaitSet == NULL) { TEVENT (Empty-Notify) ; return ; } DTRACE_MONITOR_PROBE(notify, this, object(), THREAD); int 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) { iterator->TState = ObjectWaiter::TS_ENTER ; } iterator->_notified = 1 ; 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) { // prepend(预追加) to 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) { // append(真正追加) to EntryList if (List == NULL) { iterator->_next = iterator->_prev = NULL ; _EntryList = iterator ; } else { //考虑:当前获取EntryList的tail需要遍历整个链表 //将tail访问转换为CDLL而不是使用当前的DLL,从而使访问时间固定。 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 ; } } else if (Policy == 2) { // prepend to cxq // prepend(预追加) to 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) { // append(真正追加) to 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 { ParkEvent * ev = iterator->_event ; iterator->TState = ObjectWaiter::TS_RUN ; OrderAccess::fence() ; ev->unpark() ; } if (Policy < 4) { iterator->wait_reenter_begin(this); } // _WaitSetLock protects the wait queue, not the EntryList. We could // move the add-to-EntryList operation, above, outside the critical section // protected by _WaitSetLock. In practice that's not useful. With the // exception of wait() timeouts and interrupts the monitor owner // is the only thread that grabs _WaitSetLock. There's almost no contention // on _WaitSetLock so it's not profitable to reduce the length of the // critical section. } Thread::SpinRelease (&_WaitSetLock) ; if (iterator != NULL && ObjectMonitor::_sync_Notifications != NULL) { ObjectMonitor::_sync_Notifications->inc() ; } }
void ObjectMonitor::notifyAll(TRAPS) { CHECK_OWNER(); ObjectWaiter* iterator; if (_WaitSet == NULL) { TEVENT (Empty-NotifyAll) ; return ; } DTRACE_MONITOR_PROBE(notifyAll, this, object(), THREAD); int Policy = Knob_MoveNotifyee ; int Tally = 0 ; Thread::SpinAcquire (&_WaitSetLock, "WaitSet - notifyall") ; for (;;) { iterator = DequeueWaiter () ; if (iterator == NULL) break ; TEVENT (NotifyAll - Transfer1) ; ++Tally ; // Disposition - what might we do with iterator ? // a. add it directly to the EntryList - either tail or head. // b. push it onto the front of the _cxq. // For now we use (a). guarantee (iterator->TState == ObjectWaiter::TS_WAIT, "invariant") ; guarantee (iterator->_notified == 0, "invariant") ; iterator->_notified = 1 ; if (Policy != 4) { iterator->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) { // prepend to 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) { // append to EntryList if (List == NULL) { iterator->_next = iterator->_prev = NULL ; _EntryList = iterator ; } else { // CONSIDER: finding the tail currently requires a linear-time walk of // the EntryList. We can make tail access constant-time by converting to // a CDLL instead of using our current DLL. 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 ; } } else if (Policy == 2) { // prepend to cxq // prepend to cxq 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) { // append to 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 { ParkEvent * ev = iterator->_event ; iterator->TState = ObjectWaiter::TS_RUN ; OrderAccess::fence() ; ev->unpark() ; } if (Policy < 4) { iterator->wait_reenter_begin(this); } // _WaitSetLock protects the wait queue, not the EntryList. We could // move the add-to-EntryList operation, above, outside the critical section // protected by _WaitSetLock. In practice that's not useful. With the // exception of wait() timeouts and interrupts the monitor owner // is the only thread that grabs _WaitSetLock. There's almost no contention // on _WaitSetLock so it's not profitable to reduce the length of the // critical section. } Thread::SpinRelease (&_WaitSetLock) ; if (Tally != 0 && ObjectMonitor::_sync_Notifications != NULL) { ObjectMonitor::_sync_Notifications->inc(Tally) ; } }
其实本质都是一个问题:对象锁是怎么转让的?
void ATTR ObjectMonitor::exit(TRAPS) { ...... //根据QMode 策略从同步队列 取出节点 if (QMode == 2 && _cxq != NULL) { // QMode == 2 : cxq has precedence over EntryList. // Try to directly wake a successor from the cxq. // If successful, the successor will need to unlink itself from cxq. w = _cxq ; assert (w != NULL, "invariant") ; assert (w->TState == ObjectWaiter::TS_CXQ, "Invariant") ; ExitEpilog (Self, w) ; return ; } if (QMode == 3 && _cxq != NULL) { // Aggressively drain cxq into EntryList at the first opportunity. // This policy ensure that recently-run threads live at the head of EntryList. // Drain _cxq into EntryList - bulk transfer. // First, detach _cxq. // The following loop is tantamount to: w = swap (&cxq, NULL) w = _cxq ; for (;;) { assert (w != NULL, "Invariant") ; ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ; if (u == w) break ; w = u ; } assert (w != NULL , "invariant") ; ObjectWaiter * q = NULL ; ObjectWaiter * p ; 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 ; } // Append the RATs to the EntryList // TODO: organize EntryList as a CDLL so we can locate the tail in constant-time. ObjectWaiter * Tail ; for (Tail = _EntryList ; Tail != NULL && Tail->_next != NULL ; Tail = Tail->_next) ; if (Tail == NULL) { _EntryList = w ; } else { Tail->_next = w ; w->_prev = Tail ; } // Fall thru into code that tries to wake a successor from EntryList } ...... w = _EntryList ; if (w != NULL) { guarantee (w->TState == ObjectWaiter::TS_ENTER, "invariant") ; ExitEpilog (Self, w) ; return ; } } }
void ObjectMonitor::ExitEpilog (Thread * Self, ObjectWaiter * Wakee) { { assert (_owner == Self, "invariant") ; ParkEvent * Trigger = Wakee->_event ; .... //这里对应wait 方法使用的ParkEvent.park Trigger->unpark() ; //unpark唤醒wait线程 ..... if (ObjectMonitor::_sync_Parks != NULL) { ObjectMonitor::_sync_Parks->inc() ; } }