1 // Wait/Notify/NotifyAll
  2
  3 //
  4
  5 // Note: a subset of changes to ObjectMonitor::wait()
  6
  7 // will need to be replicated in complete_exit above
  8
  9 void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
 10
 11    Thread * const Self = THREAD ;
 12
 13    assert(Self->is_Java_thread(), "Must be Java thread!");
 14
 15    JavaThread *jt = (JavaThread *)THREAD;
 16
 17
 18    DeferredInitialize () ;
 19
 20
 21    // Throw IMSX or IEX.
 22
 23    CHECK_OWNER();
 24
 25
 26    EventJavaMonitorWait event;
 27
 28
 29    // check for a pending interrupt
 30
 31    if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {
 32
 33      // post monitor waited event.  Note that this is past-tense, we are done waiting.
 34
 35      if (JvmtiExport::should_post_monitor_waited()) {
 36
 37         // Note: 'false' parameter is passed here because the
 38
 39         // wait was not timed out due to thread interrupt.
 40
 41         JvmtiExport::post_monitor_waited(jt, this, false);
 42
 43
 44         // In this short circuit of the monitor wait protocol, the
 45
 46         // current thread never drops ownership of the monitor and
 47
 48         // never gets added to the wait queue so the current thread
 49
 50         // cannot be made the successor. This means that the
 51
 52         // JVMTI_EVENT_MONITOR_WAITED event handler cannot accidentally
 53
 54         // consume an unpark() meant for the ParkEvent associated with
 55
 56         // this ObjectMonitor.
 57
 58      }
 59
 60      if (event.should_commit()) {
 61
 62        post_monitor_wait_event(&event, 0, millis, false);
 63
 64      }
 65
 66      TEVENT (Wait - Throw IEX) ;
 67
 68      THROW(vmSymbols::java_lang_InterruptedException());
 69
 70      return ;
 71
 72    }
 73
 74
 75    TEVENT (Wait) ;
 76
 77
 78    assert (Self->_Stalled == 0, "invariant") ;
 79
 80    Self->_Stalled = intptr_t(this) ;
 81
 82    jt->set_current_waiting_monitor(this);
 83
 84
 85    // create a node to be put into the queue
 86
 87    // Critically, after we reset() the event but prior to park(), we must check
 88
 89    // for a pending interrupt.
 90    将当前线程包装成ObjectWaiter对象,并且状态为TS_WAIT,这里对应的是jstack看到的线程状态WAITING
 91    ObjectWaiter node(Self);
 92
 93    node.TState = ObjectWaiter::TS_WAIT ;
 94
 95    Self->_ParkEvent->reset() ;
 96
 97    OrderAccess::fence();          // ST into Event; membar ; LD interrupted-flag
 98
 99
100    // Enter the waiting queue, which is a circular doubly linked list in this case
101
102    // but it could be a priority queue or any data structure.
103
104    // _WaitSetLock protects the wait queue.  Normally the wait queue is accessed only
105
106    // by the the owner of the monitor *except* in the case where park()
107
108    // returns because of a timeout of interrupt.  Contention is exceptionally rare
109
110    // so we use a simple spin-lock instead of a heavier-weight blocking lock.
111
112
113    Thread::SpinAcquire (&_WaitSetLock, "WaitSet - add") ;
114    这个ObjectWaiter对象被放入了_WaitSet中,_WaitSet是个环形双向链表(circular doubly linked list)
115    AddWaiter (&node) ;
116
117    Thread::SpinRelease (&_WaitSetLock) ;
118
119
120    if ((SyncFlags & 4) == 0) {
121
122       _Responsible = NULL ;
123
124    }
125
126    intptr_t save = _recursions; // record the old recursion count
127
128    _waiters++;                  // increment the number of waiters
129
130    _recursions = 0;             // set the recursion level to be 1
131
132    exit (true, Self) ;                    // exit the monitor
133
134    guarantee (_owner != Self, "invariant") ;
135
136
137    // The thread is on the WaitSet list - now park() it.
138
139    // On MP systems it's conceivable that a brief spin before we park
140
141    // could be profitable.
142
143    //
144
145    // TODO-FIXME: change the following logic to a loop of the form
146
147    //   while (!timeout && !interrupted && _notified == 0) park()
148
149
150    int ret = OS_OK ;
151
152    int WasNotified = 0 ;
153
154    { // State transition wrappers
155
156      OSThread* osthread = Self->osthread();
157
158      OSThreadWaitState osts(osthread, true);
159
160      {
161
162        ThreadBlockInVM tbivm(jt);
163
164        // Thread is in thread_blocked state and oop access is unsafe.
165
166        jt->set_suspend_equivalent();
167
168
169        if (interruptible && (Thread::is_interrupted(THREAD, false) || HAS_PENDING_EXCEPTION)) {
170
171            // Intentionally empty
172
173        } else
174
175        if (node._notified == 0) {
176
177          if (millis <= 0) {
178         当前线程通过park()方法开始挂起(suspend)
179             Self->_ParkEvent->park () ;
180
181          } else {
182
183             ret = Self->_ParkEvent->park (millis) ;
184
185          }
186
187        }
188
189
190        // were we externally suspended while we were waiting?
191
192        if (ExitSuspendEquivalent (jt)) {
193
194           // TODO-FIXME: add -- if succ == Self then succ = null.
195
196           jt->java_suspend_self();
197
198        }
199
200
201      } // Exit thread safepoint: transition _thread_blocked -> _thread_in_vm
202
203
204
205      // Node may be on the WaitSet, the EntryList (or cxq), or in transition
206
207      // from the WaitSet to the EntryList.
208
209      // See if we need to remove Node from the WaitSet.
210
211      // We use double-checked locking to avoid grabbing _WaitSetLock
212
213      // if the thread is not on the wait queue.
214
215      //
216
217      // Note that we don't need a fence before the fetch of TState.
218
219      // In the worst case we'll fetch a old-stale value of TS_WAIT previously
220
221      // written by the is thread. (perhaps the fetch might even be satisfied
222
223      // by a look-aside into the processor's own store buffer, although given
224
225      // the length of the code path between the prior ST and this load that's
226
227      // highly unlikely).  If the following LD fetches a stale TS_WAIT value
228
229      // then we'll acquire the lock and then re-fetch a fresh TState value.
230
231      // That is, we fail toward safety.
232
233
234      if (node.TState == ObjectWaiter::TS_WAIT) {
235
236          Thread::SpinAcquire (&_WaitSetLock, "WaitSet - unlink") ;
237
238          if (node.TState == ObjectWaiter::TS_WAIT) {
239
240             DequeueSpecificWaiter (&node) ;       // unlink from WaitSet
241
242             assert(node._notified == 0, "invariant");
243
244             node.TState = ObjectWaiter::TS_RUN ;
245
246          }
247
248          Thread::SpinRelease (&_WaitSetLock) ;
249
250      }
251
252
253      // The thread is now either on off-list (TS_RUN),
254
255      // on the EntryList (TS_ENTER), or on the cxq (TS_CXQ).
256
257      // The Node's TState variable is stable from the perspective of this thread.
258
259      // No other threads will asynchronously modify TState.
260
261      guarantee (node.TState != ObjectWaiter::TS_WAIT, "invariant") ;
262
263      OrderAccess::loadload() ;
264
265      if (_succ == Self) _succ = NULL ;
266
267      WasNotified = node._notified ;
268
269
270      // Reentry phase -- reacquire the monitor.
271
272      // re-enter contended monitor after object.wait().
273
274      // retain OBJECT_WAIT state until re-enter successfully completes
275
276      // Thread state is thread_in_vm and oop access is again safe,
277
278      // although the raw address of the object may have changed.
279
280      // (Don't cache naked oops over safepoints, of course).
281
282
283      // post monitor waited event. Note that this is past-tense, we are done waiting.
284
285      if (JvmtiExport::should_post_monitor_waited()) {
286
287        JvmtiExport::post_monitor_waited(jt, this, ret == OS_TIMEOUT);
288
289
290        if (node._notified != 0 && _succ == Self) {
291
292          // In this part of the monitor wait-notify-reenter protocol it
293
294          // is possible (and normal) for another thread to do a fastpath
295
296          // monitor enter-exit while this thread is still trying to get
297
298          // to the reenter portion of the protocol.
299
300          //
301
302          // The ObjectMonitor was notified and the current thread is
303
304          // the successor which also means that an unpark() has already
305
306          // been done. The JVMTI_EVENT_MONITOR_WAITED event handler can
307
308          // consume the unpark() that was done when the successor was
309
310          // set because the same ParkEvent is shared between Java
311
312          // monitors and JVM/TI RawMonitors (for now).
313
314          //
315
316          // We redo the unpark() to ensure forward progress, i.e., we
317
318          // don't want all pending threads hanging (parked) with none
319
320          // entering the unlocked monitor.
321
322          node._event->unpark();
323
324        }
325
326      }
327
328
329      if (event.should_commit()) {
330
331        post_monitor_wait_event(&event, node._notifier_tid, millis, ret == OS_TIMEOUT);
332
333      }
334
335
336      OrderAccess::fence() ;
337
338
339      assert (Self->_Stalled != 0, "invariant") ;
340
341      Self->_Stalled = 0 ;
342
343
344      assert (_owner != Self, "invariant") ;
345
346      ObjectWaiter::TStates v = node.TState ;
347
348      if (v == ObjectWaiter::TS_RUN) {
349
350          enter (Self) ;
351
352      } else {
353
354          guarantee (v == ObjectWaiter::TS_ENTER || v == ObjectWaiter::TS_CXQ, "invariant") ;
355
356          ReenterI (Self, &node) ;
357
358          node.wait_reenter_end(this);
359
360      }
361
362
363      // Self has reacquired the lock.
364
365      // Lifecycle - the node representing Self must not appear on any queues.
366
367      // Node is about to go out-of-scope, but even if it were immortal we wouldn't
368
369      // want residual elements associated with this thread left on any lists.
370
371      guarantee (node.TState == ObjectWaiter::TS_RUN, "invariant") ;
372
373      assert    (_owner == Self, "invariant") ;
374
375      assert    (_succ != Self , "invariant") ;
376
377    } // OSThreadWaitState()
378
379
380    jt->set_current_waiting_monitor(NULL);
381
382
383    guarantee (_recursions == 0, "invariant") ;
384
385    _recursions = save;     // restore the old recursion count
386
387    _waiters--;             // decrement the number of waiters
388
389
390    // Verify a few postconditions
391
392    assert (_owner == Self       , "invariant") ;
393
394    assert (_succ  != Self       , "invariant") ;
395
396    assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
397
398
399    if (SyncFlags & 32) {
400
401       OrderAccess::fence() ;
402
403    }
404
405
406    // check if the notification happened
407
408    if (!WasNotified) {
409
410      // no, it could be timeout or Thread.interrupt() or both
411
412      // check for interrupt event, otherwise it is timeout
413
414      if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {
415
416        TEVENT (Wait - throw IEX from epilog) ;
417
418        THROW(vmSymbols::java_lang_InterruptedException());
419
420      }
421
422    }
423
424
425    // NOTE: Spurious wake up will be consider as timeout.
426
427    // Monitor notify has precedence over thread interrupt.
428
429 }

ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS)

总结:wait()方法的内容

1. 把当前线程包装成ObjectWaiter对象,状态为TS_WAIT;

2. ObjectWaiter对象被放入_WaitSet中;

3. 当前线程挂起;

01-09 14:57