讓我們想象一下有人同步返回一個int的方法:java是否刪除/優化不必要的同步語句?
int whatever = 33;
...
public synchronized int getWathever() {
return this.whatever;
}
我們從整數原子地修改Java的規範認識。因此,聲明不是必需的。
編譯器會刪除/優化它嗎?
讓我們想象一下有人同步返回一個int的方法:java是否刪除/優化不必要的同步語句?
int whatever = 33;
...
public synchronized int getWathever() {
return this.whatever;
}
我們從整數原子地修改Java的規範認識。因此,聲明不是必需的。
編譯器會刪除/優化它嗎?
不,那根本是不可能期間舉行。如果編譯器和JVM這樣做,很可能會違反由Java編程語言內存模型設置的約束。
更具體地說,Java語言規範中聲明的順序將被違反。如果編譯器或一個JVM *分別以除去任何「不需要的」同步,然後,進行將違反同步順序上放置由開發者任何假設的任何進一步的優化(和之前發生)的關係。在您的具體情況下,在讀取之前,在編譯器/ JVM中遵循Java內存模型的任何寫入整數的操作都會發生。
刪除同步的編譯器/ JVM只會導致違反內存模型的環境。例如,可以在讀取整數值之前執行內嵌方法,而無需編譯器/ JVM放置內存屏障,從而允許從緩存值讀取陳舊值。
*請注意,編譯器/ JVM duo的引用是故意的。編譯器只會發出符合JLS的字節碼;一個JVM可能只會有一個內存模型的需求仍然可能被違反的錯誤。爲了完整的內存模型,編譯器和JVM都應該符合內存模型設定的要求。
這是絕對不安全的刪除「同步」,如果意圖是使線程安全的,除非你保證在一些其他的方式int變量正確同步到主內存,所以在這種情況下,沒有。
但是(除非我錯了)只修改long和double需要volatile,否? – JVerstry
不,除非你只能在單核處理器上運行這個程序。這不是關於原子寫入和讀取。它是關於值在CPU緩存和主內存之間來回傳送。在多線程運行且沒有「同步」的多核機器上,不同的線程可以並且幾乎可以肯定會看到同一個變量的不同值,因爲每個內核在其緩存中與其他內存和主內存中的值不同。 –
有些情況下虛擬機可以消除鎖定。例如
逃逸分析
int bar()
Foo foo = new Foo();
return foo.getWhatever();
VM可以有理由相信foo是沒有任何其他線程可見的,因此沒有人將嘗試將其鎖定,therfore的getWhatever
方法的鎖定可以被丟棄。
鎖粗
Foo foo = ...;
void bar()
a();
foo.getWhatever();
b();
foo.getWhatever();
c();
可以合法合併,以節省一個鎖定動作
void bar()
synchronized(foo)
a();
foo.getWhatever_without_lock();
b();
foo.getWhatever_without_lock();
c();
另一個好消息是,因爲鎖定區域是如此之短,由於自適應鎖定,VM極有可能會使用自旋鎖定;由於鎖定失敗而導致線程掛起的可能性很小。
你能給這個參考嗎? –
@Ryan只是谷歌的條款 – irreputable
另請參見http://stackoverflow.com/questions/18996783/what-is-the-synchronization-cost-of-calling-a-synchronized-method-from-a-synchro – Raedwald
令人懷疑。如果你(程序員)認爲它是不必要的,爲什麼在代碼中指定它? – Hyperbole
我不會,但是讓我們說我依賴於第三方代碼或者我沒有自己寫的代碼。 – JVerstry