2014-02-07 142 views
18

我期待在我的Java應用程序的線程轉儲,並已注意到,有時反而顯示出「鎖定」,我看「淘汰」這個關鍵字,如下所示:Java堆棧跟蹤中的「消除」是什麼意思?

"Worker [4]" prio=10 tid=0x00007fb1262d8800 nid=0x89a0 in Object.wait() [0x00007fb15b147000] 
    java.lang.Thread.State: WAITING (on object monitor) 
     at java.lang.Object.wait(Native Method) 
     at java.lang.Object.wait(Object.java:503) 
     at com.myapp.common.util.WaitableQueue.getAll(WaitableQueue.java:152) 
     - eliminated <0x00000004d0d28e18> (a com.myapp.common.util.balq.SingleQueueQController$_WorkerQueue) 
     at com.myapp.common.util.balq.SingleQueueQController$_WorkerQueue.getAll(SingleQueueQController.java:3527) 
     - locked <0x00000004d0d28e18> (a com.myapp.common.util.balq.SingleQueueQController$_WorkerQueue) 
     at com.myapp.common.util.AbstractWorker.read(AbstractWorker.java:678) 
     at com.myapp.common.util.AbstractWorker.runBulk(AbstractWorker.java:541) 
     at com.myapp.common.util.AbstractWorker.run(AbstractWorker.java:343) 

出人意料的是,我可以在谷歌上找不到任何關於此事的信息。 「鎖定」和「消除」關鍵字之間有什麼區別?

+4

可能是指[lock elision](http://stackoverflow.com/questions/7029326/does-the-clr-perform-lock-elision-optimization-if-not-why-not)。 – Dirk

+0

謝謝你的偉大的文章的鏈接!這肯定會符合我所看到的。 – zedix

+5

@Dirk你可能會考慮回答這個問題。這樣它就不會顯示爲沒有答案。 –

回答

12

它表示冗餘鎖已在字節碼中被刪除。

我總是發現源代碼是一個很好的開始這樣的事情的地方。的hotspot/src/share/vm/opto/callnode.cpp從OpenJDK的審查了以下有趣的評論:

// Redundant lock elimination 
// 
// There are various patterns of locking where we release and 
// immediately reacquire a lock in a piece of code where no operations 
// occur in between that would be observable. In those cases we can 
// skip releasing and reacquiring the lock without violating any 
// fairness requirements. Doing this around a loop could cause a lock 
// to be held for a very long time so we concentrate on non-looping 
// control flow. We also require that the operations are fully 
// redundant meaning that we don't introduce new lock operations on 
// some paths so to be able to eliminate it on others ala PRE. This 
// would probably require some more extensive graph manipulation to 
// guarantee that the memory edges were all handled correctly. 
// 
// Assuming p is a simple predicate which can't trap in any way and s 
// is a synchronized method consider this code: 
// 
// s(); 
// if (p) 
//  s(); 
// else 
//  s(); 
// s(); 
// 
// 1. The unlocks of the first call to s can be eliminated if the 
// locks inside the then and else branches are eliminated. 
// 
// 2. The unlocks of the then and else branches can be eliminated if 
// the lock of the final call to s is eliminated. 
// 
// Either of these cases subsumes the simple case of sequential control flow 

所以從上面的,它似乎(至少在OpenJDK的),其消除意味着該鎖由JVM通過一個或多個組的維護髮布/獲取說明。

回顧javaVFrame::print_lock_info_on()hotspot/src/share/vm/runtime/vframe.cpp示出了檢查和輸出發生:

// Print out all monitors that we have locked or are trying to lock 
GrowableArray<MonitorInfo*>* mons = monitors(); 
if (!mons->is_empty()) { 
    bool found_first_monitor = false; 
    for (int index = (mons->length()-1); index >= 0; index--) { 
    MonitorInfo* monitor = mons->at(index); 
    if (monitor->eliminated() && is_compiled_frame()) { // Eliminated in compiled code 
     if (monitor->owner_is_scalar_replaced()) { 
     Klass* k = Klass::cast(monitor->owner_klass()); 
     st->print("\t- eliminated <owner is scalar replaced> (a %s)", k->external_name()); 
     } else { 
     oop obj = monitor->owner(); 
     if (obj != NULL) { 
      print_locked_object_class_name(st, obj, "eliminated"); 
     } 
     } 
     continue; 

進一步說明包括所述一個以上的組合也暗示更換鎖並用NOP解鎖指令。

我讀德克提到有關lock elision文檔,它似乎是鎖粗化,而不是省音:

,可用於減少鎖定成本另一種優化是鎖粗。鎖定粗化是合併使用相同鎖定對象的相鄰同步塊的過程。如果編譯器不能使用鎖定elision消除鎖定,則它可以通過使用鎖定粗化來減少開銷。

但說實話,差異非常微妙,最終效果幾乎相同 - 您可以消除不必要的鎖定和解鎖。

相關問題