1 void ATTR ObjectMonitor::exit(bool not_suspended, TRAPS) { 2 3 Thread * Self = THREAD ; 4 5 if (THREAD != _owner) { 6 7 if (THREAD->is_lock_owned((address) _owner)) { 8 9 // Transmute _owner from a BasicLock pointer to a Thread address. 10 11 // We don't need to hold _mutex for this transition. 12 13 // Non-null to Non-null is safe as long as all readers can 14 15 // tolerate either flavor. 16 17 assert (_recursions == 0, "invariant") ; 18 19 _owner = THREAD ; 20 21 _recursions = 0 ; 22 23 OwnerIsThread = 1 ; 24 25 } else { 26 27 // NOTE: we need to handle unbalanced monitor enter/exit 28 29 // in native code by throwing an exception. 30 31 // TODO: Throw an IllegalMonitorStateException ? 32 33 TEVENT (Exit - Throw IMSX) ; 34 35 assert(false, "Non-balanced monitor enter/exit!"); 36 37 if (false) { 38 39 THROW(vmSymbols::java_lang_IllegalMonitorStateException()); 40 41 } 42 43 return; 44 45 } 46 47 } 48 49 此处是偏向锁逻辑,偏向次数减一后直接返回 50 if (_recursions != 0) { 51 52 _recursions--; // this is simple recursive enter 53 54 TEVENT (Inflated exit - recursive) ; 55 56 return ; 57 58 } 59 60 61 // Invariant: after setting Responsible=null an thread must execute 62 63 // a MEMBAR or other serializing instruction before fetching EntryList|cxq. 64 65 if ((SyncFlags & 4) == 0) { 66 67 _Responsible = NULL ; 68 69 } 70 71 72 #if INCLUDE_TRACE 73 74 // get the owner's thread id for the MonitorEnter event 75 76 // if it is enabled and the thread isn't suspended 77 78 if (not_suspended && Tracing::is_event_enabled(TraceJavaMonitorEnterEvent)) { 79 80 _previous_owner_tid = SharedRuntime::get_java_tid(Self); 81 82 } 83 84 #endif 85 86 87 for (;;) { 88 89 assert (THREAD == _owner, "invariant") ; 90 91 92 93 if (Knob_ExitPolicy == 0) { 94 95 // release semantics: prior loads and stores from within the critical section 96 97 // must not float (reorder) past the following store that drops the lock. 98 99 // On SPARC that requires MEMBAR #loadstore|#storestore. 100 101 // But of course in TSO #loadstore|#storestore is not required. 102 103 // I'd like to write one of the following: 104 105 // A. OrderAccess::release() ; _owner = NULL 106 107 // B. OrderAccess::loadstore(); OrderAccess::storestore(); _owner = NULL; 108 109 // Unfortunately OrderAccess::release() and OrderAccess::loadstore() both 110 111 // store into a _dummy variable. That store is not needed, but can result 112 113 // in massive wasteful coherency traffic on classic SMP systems. 114 115 // Instead, I use release_store(), which is implemented as just a simple 116 117 // ST on x64, x86 and SPARC. 118 119 OrderAccess::release_store_ptr (&_owner, NULL) ; // drop the lock 120 121 OrderAccess::storeload() ; // See if we need to wake a successor 122 123 if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) { 124 125 TEVENT (Inflated exit - simple egress) ; 126 127 return ; 128 129 } 130 131 TEVENT (Inflated exit - complex egress) ; 132 133 134 // Normally the exiting thread is responsible for ensuring succession, 135 136 // but if other successors are ready or other entering threads are spinning 137 138 // then this thread can simply store NULL into _owner and exit without 139 140 // waking a successor. The existence of spinners or ready successors 141 142 // guarantees proper succession (liveness). Responsibility passes to the 143 144 // ready or running successors. The exiting thread delegates the duty. 145 146 // More precisely, if a successor already exists this thread is absolved 147 148 // of the responsibility of waking (unparking) one. 149 150 // 151 152 // The _succ variable is critical to reducing futile wakeup frequency. 153 154 // _succ identifies the "heir presumptive" thread that has been made 155 156 // ready (unparked) but that has not yet run. We need only one such 157 158 // successor thread to guarantee progress. 159 160 // See http://www.usenix.org/events/jvm01/full_papers/dice/dice.pdf 161 162 // section 3.3 "Futile Wakeup Throttling" for details. 163 164 // 165 166 // Note that spinners in Enter() also set _succ non-null. 167 168 // In the current implementation spinners opportunistically set 169 170 // _succ so that exiting threads might avoid waking a successor. 171 172 // Another less appealing alternative would be for the exiting thread 173 174 // to drop the lock and then spin briefly to see if a spinner managed 175 176 // to acquire the lock. If so, the exiting thread could exit 177 178 // immediately without waking a successor, otherwise the exiting 179 180 // thread would need to dequeue and wake a successor. 181 182 // (Note that we'd need to make the post-drop spin short, but no 183 184 // shorter than the worst-case round-trip cache-line migration time. 185 186 // The dropped lock needs to become visible to the spinner, and then 187 188 // the acquisition of the lock by the spinner must become visible to 189 190 // the exiting thread). 191 192 // 193 194 195 // It appears that an heir-presumptive (successor) must be made ready. 196 197 // Only the current lock owner can manipulate the EntryList or 198 199 // drain _cxq, so we need to reacquire the lock. If we fail 200 201 // to reacquire the lock the responsibility for ensuring succession 202 203 // falls to the new owner. 204 205 // 206 207 if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) { 208 209 return ; 210 211 } 212 213 TEVENT (Exit - Reacquired) ; 214 215 } else { 216 217 if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) { 218 219 OrderAccess::release_store_ptr (&_owner, NULL) ; // drop the lock 220 221 OrderAccess::storeload() ; 222 223 // Ratify the previously observed values. 224 225 if (_cxq == NULL || _succ != NULL) { 226 227 TEVENT (Inflated exit - simple egress) ; 228 229 return ; 230 231 } 232 233 234 // inopportune interleaving -- the exiting thread (this thread) 235 236 // in the fast-exit path raced an entering thread in the slow-enter 237 238 // path. 239 240 // We have two choices: 241 242 // A. Try to reacquire the lock. 243 244 // If the CAS() fails return immediately, otherwise 245 246 // we either restart/rerun the exit operation, or simply 247 248 // fall-through into the code below which wakes a successor. 249 250 // B. If the elements forming the EntryList|cxq are TSM 251 252 // we could simply unpark() the lead thread and return 253 254 // without having set _succ. 255 256 if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) { 257 258 TEVENT (Inflated exit - reacquired succeeded) ; 259 260 return ; 261 262 } 263 264 TEVENT (Inflated exit - reacquired failed) ; 265 266 } else { 267 268 TEVENT (Inflated exit - complex egress) ; 269 270 } 271 272 } 273 274 275 guarantee (_owner == THREAD, "invariant") ; 276 277 278 ObjectWaiter * w = NULL ; 279 280 int QMode = Knob_QMode ; 281 282 QMode = 2,并且_cxq非空:取_cxq队列排头位置的ObjectWaiter对象,调用ExitEpilog方法,该方法会唤醒ObjectWaiter对象的线程,此处会立即返回,后面的代码不会执行了 283 if (QMode == 2 && _cxq != NULL) { 284 285 // QMode == 2 : cxq has precedence over EntryList. 286 287 // Try to directly wake a successor from the cxq. 288 289 // If successful, the successor will need to unlink itself from cxq. 290 291 w = _cxq ; 292 293 assert (w != NULL, "invariant") ; 294 295 assert (w->TState == ObjectWaiter::TS_CXQ, "Invariant") ; 296 297 ExitEpilog (Self, w) ; 298 299 return ; 300 301 } 302 303 QMode = 3,并且_cxq非空:把_cxq队列首元素放入_EntryList的尾部; 304 if (QMode == 3 && _cxq != NULL) { 305 306 // Aggressively drain cxq into EntryList at the first opportunity. 307 308 // This policy ensure that recently-run threads live at the head of EntryList. 309 310 // Drain _cxq into EntryList - bulk transfer. 311 312 // First, detach _cxq. 313 314 // The following loop is tantamount to: w = swap (&cxq, NULL) 315 316 w = _cxq ; 317 318 for (;;) { 319 320 assert (w != NULL, "Invariant") ; 321 322 ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ; 323 324 if (u == w) break ; 325 326 w = u ; 327 328 } 329 330 assert (w != NULL , "invariant") ; 331 332 333 ObjectWaiter * q = NULL ; 334 335 ObjectWaiter * p ; 336 337 for (p = w ; p != NULL ; p = p->_next) { 338 339 guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ; 340 341 p->TState = ObjectWaiter::TS_ENTER ; 342 343 p->_prev = q ; 344 345 q = p ; 346 347 } 348 349 350 // Append the RATs to the EntryList 351 352 // TODO: organize EntryList as a CDLL so we can locate the tail in constant-time. 353 354 ObjectWaiter * Tail ; 355 356 for (Tail = _EntryList ; Tail != NULL && Tail->_next != NULL ; Tail = Tail->_next) ; 357 358 if (Tail == NULL) { 359 360 _EntryList = w ; 361 362 } else { 363 364 Tail->_next = w ; 365 366 w->_prev = Tail ; 367 368 } 369 370 371 // Fall thru into code that tries to wake a successor from EntryList 372 373 } 374 375 Mode = 4,并且_cxq非空:把_cxq队列首元素放入_EntryList的头部; 376 if (QMode == 4 && _cxq != NULL) { 377 378 // Aggressively drain cxq into EntryList at the first opportunity. 379 380 // This policy ensure that recently-run threads live at the head of EntryList. 381 382 383 // Drain _cxq into EntryList - bulk transfer. 384 385 // First, detach _cxq. 386 387 // The following loop is tantamount to: w = swap (&cxq, NULL) 388 389 w = _cxq ; 390 391 for (;;) { 392 393 assert (w != NULL, "Invariant") ; 394 395 ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ; 396 397 if (u == w) break ; 398 399 w = u ; 400 401 } 402 403 assert (w != NULL , "invariant") ; 404 405 406 ObjectWaiter * q = NULL ; 407 408 ObjectWaiter * p ; 409 410 for (p = w ; p != NULL ; p = p->_next) { 411 412 guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ; 413 414 p->TState = ObjectWaiter::TS_ENTER ; 415 416 p->_prev = q ; 417 418 q = p ; 419 420 } 421 422 423 // Prepend the RATs to the EntryList 424 425 if (_EntryList != NULL) { 426 427 q->_next = _EntryList ; 428 429 _EntryList->_prev = q ; 430 431 } 432 433 _EntryList = w ; 434 435 436 // Fall thru into code that tries to wake a successor from EntryList 437 438 } 439 440 441 w = _EntryList ; 442 443 if (w != NULL) { 444 445 // I'd like to write: guarantee (w->_thread != Self). 446 447 // But in practice an exiting thread may find itself on the EntryList. 448 449 // Lets say thread T1 calls O.wait(). Wait() enqueues T1 on O's waitset and 450 451 // then calls exit(). Exit release the lock by setting O._owner to NULL. 452 453 // Lets say T1 then stalls. T2 acquires O and calls O.notify(). The 454 455 // notify() operation moves T1 from O's waitset to O's EntryList. T2 then 456 457 // release the lock "O". T2 resumes immediately after the ST of null into 458 459 // _owner, above. T2 notices that the EntryList is populated, so it 460 461 // reacquires the lock and then finds itself on the EntryList. 462 463 // Given all that, we have to tolerate the circumstance where "w" is 464 465 // associated with Self. 466 467 assert (w->TState == ObjectWaiter::TS_ENTER, "invariant") ; 468 469 ExitEpilog (Self, w) ; 470 471 return ; 472 473 } 474 475 476 // If we find that both _cxq and EntryList are null then just 477 478 // re-run the exit protocol from the top. 479 480 w = _cxq ; 481 482 if (w == NULL) continue ; 483 484 485 // Drain _cxq into EntryList - bulk transfer. 486 487 // First, detach _cxq. 488 489 // The following loop is tantamount to: w = swap (&cxq, NULL) 490 491 for (;;) { 492 493 assert (w != NULL, "Invariant") ; 494 495 ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ; 496 497 if (u == w) break ; 498 499 w = u ; 500 501 } 502 503 TEVENT (Inflated exit - drain cxq into EntryList) ; 504 505 506 assert (w != NULL , "invariant") ; 507 508 assert (_EntryList == NULL , "invariant") ; 509 510 511 // Convert the LIFO SLL anchored by _cxq into a DLL. 512 513 // The list reorganization step operates in O(LENGTH(w)) time. 514 515 // It's critical that this step operate quickly as 516 517 // "Self" still holds the outer-lock, restricting parallelism 518 519 // and effectively lengthening the critical section. 520 521 // Invariant: s chases t chases u. 522 523 // TODO-FIXME: consider changing EntryList from a DLL to a CDLL so 524 525 // we have faster access to the tail. 526 527 528 if (QMode == 1) { 529 530 // QMode == 1 : drain cxq to EntryList, reversing order 531 532 // We also reverse the order of the list. 533 534 ObjectWaiter * s = NULL ; 535 536 ObjectWaiter * t = w ; 537 538 ObjectWaiter * u = NULL ; 539 540 while (t != NULL) { 541 542 guarantee (t->TState == ObjectWaiter::TS_CXQ, "invariant") ; 543 544 t->TState = ObjectWaiter::TS_ENTER ; 545 546 u = t->_next ; 547 548 t->_prev = u ; 549 550 t->_next = s ; 551 552 s = t; 553 554 t = u ; 555 556 } 557 558 _EntryList = s ; 559 560 assert (s != NULL, "invariant") ; 561 562 } else { 563 564 // QMode == 0 or QMode == 2 565 566 _EntryList = w ; 567 568 ObjectWaiter * q = NULL ; 569 570 ObjectWaiter * p ; 571 572 for (p = w ; p != NULL ; p = p->_next) { 573 574 guarantee (p->TState == ObjectWaiter::TS_CXQ, "Invariant") ; 575 576 p->TState = ObjectWaiter::TS_ENTER ; 577 578 p->_prev = q ; 579 580 q = p ; 581 582 } 583 584 } 585 586 587 // In 1-0 mode we need: ST EntryList; MEMBAR #storestore; ST _owner = NULL 588 589 // The MEMBAR is satisfied by the release_store() operation in ExitEpilog(). 590 591 592 // See if we can abdicate to a spinner instead of waking a thread. 593 594 // A primary goal of the implementation is to reduce the 595 596 // context-switch rate. 597 598 if (_succ != NULL) continue; 599 600 601 w = _EntryList ; 602 603 if (w != NULL) { 604 605 guarantee (w->TState == ObjectWaiter::TS_ENTER, "invariant") ; 606 607 ExitEpilog (Self, w) ; 608 609 return ; 610 611 } 612 613 } 614 615 }
总结释放锁内容:
1. 偏向锁逻辑;
2. 根据QMode的不同,将ObjectWaiter从_cxq或者_EntryList中取出后唤醒;
3. 唤醒的元素会继续执行挂起前的代码,按照我们之前的分析,线程唤醒后,就会通过CAS去竞争锁;
- 根据QMode的不同,将ObjectWaiter从_cxq或者_EntryList中取出后唤醒;