簡體   English   中英

可以將同步塊簡化為字節碼級別的Try-Finally塊嗎?

[英]Can a Synchronized Block be simplified to a Try-Finally Block on the Bytecode Level?

編寫我自己的編譯器用於類似Java的語言,我在編譯synchronized blocks時遇到問題。 我想出了以下想法,將它們簡化為try-finally塊:

synchonized (obj) {
     statements...
}

可以替換

Object _lock = obj
_monitorEnter(lock)
try {
    statements...
}
finally {
    _monitorExit(lock)
}

_monitorEnter_monitorExit代表MONITORENTERMONITOREXIT說明。

我是否正確地假設如何編譯synchronized ,或者我錯過了什么?

編輯

我的實現以前對body中的returnthrow語句有一些特殊處理。 基本上,它會在每個*RETURNTHROW指令之前手動加載所有lock變量和MONITOREXIT 這是由finally塊處理的,還是我還需要這些檢查?

你的假設是正確的。 Java語言中的synchronized塊使用monitorentermonitorexit指令實現。 您可以在此處查看JVM規范詳細信息。

Java虛擬機中的同步由監視器進入和退出實現,顯式地(通過使用monitorenter和monitorexit指令)或隱式地(通過方法調用和返回指令)。

編譯器生成的字節碼將處理synchronized體內拋出的所有異常,因此您的try-finally方法在這里工作正常。

finally語句的規范沒有說明釋放監視器的任何信息。 第一個鏈接中提供的示例顯示了包含在synchronized塊中的簡單方法的字節碼。 如您所見,處理任何可能的異常以確保monitorexit指令執行。 您應該在編譯器中實現相同的行為(編寫將在finally語句中釋放monitor的代碼)。

void onlyMe(Foo f) {
    synchronized(f) {
        doSomething();
    }
}

Method void onlyMe(Foo)
0   aload_1             // Push f
1   dup                 // Duplicate it on the stack
2   astore_2            // Store duplicate in local variable 2
3   monitorenter        // Enter the monitor associated with f
4   aload_0             // Holding the monitor, pass this and...
5   invokevirtual #5    // ...call Example.doSomething()V
8   aload_2             // Push local variable 2 (f)
9   monitorexit         // Exit the monitor associated with f
10  goto 18             // Complete the method normally
13  astore_3            // In case of any throw, end up here
14  aload_2             // Push local variable 2 (f)
15  monitorexit         // Be sure to exit the monitor!
16  aload_3             // Push thrown value...
17  athrow              // ...and rethrow value to the invoker
18  return              // Return in the normal case
Exception table:
From    To      Target      Type
4       10      13          any
13      16      13          any

正如您所猜測的那樣,Java編譯器將同步塊編譯為類似於try-finally的內容。 但是,有一個小的區別 - 異常處理捕獲monitorexit拋出的異常並且無限地嘗試釋放鎖。 在Java中沒有辦法像這樣指定控制流。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM