2015-04-04 93 views
0

在併發程序,這是安全的:getter上的volatile和setter上的同步與synchronized上的同步?


private volatile int i; 

public int getI() { 
    return i; 
} 

public synchronized incrementI() { 
    i++; 
} 

根據我所瞭解的synchronize,只有在獲取同一對象上的鎖定監視器的線程上,才能保證在i上可用的更改。 所以我認爲,上面的代碼是不安全的。請確認是否屬實,否則請說明。 謝謝。

回答

1

此代碼是線程安全的。同步方法內的更改傳遞到所有線程。 因爲你已經使它變得不穩定,所有的線程都不會緩存它,所以會得到最新的拷貝。

而且這個線程將有助於Java volatile modifier and synchronized blocks

+1

不幸的是,這個答案不正確。 「同步方法內部的更改都不會傳遞到所有線程」,也不會「如果您使其變爲易失性,所有線程都不會將其緩存」。這是一個正確的答案:http://stackoverflow.com/a/29446437/2613885 – 2015-04-04 12:32:46

+0

@AlekseyShipilev如果你不使變量易變,那麼單獨的線程緩存其堆棧中的值。還更新同步塊中的變量,並更新其存儲它的所有線程中的值。你同意嗎?你所說的最終會導致這種情況。那麼如何來回答是錯誤的。 – Lokesh 2015-04-04 13:17:44

+0

看到這篇文章:http://www.javamex.com/tutorials/synchronization_volatile.shtml – Lokesh 2015-04-04 13:18:59

0

由於整數i類的同步實例方法將工作的私有實例變量。您需要確保您添加到修改i的類的所有方法都必須使用同一個對象監視器進行同步。

請注意i ++不是自動錶達式,所以只有volatile纔會起作用。

您可以像這樣使用AtomicInteger作爲單個值。

1

幾乎精確的例子在「JMM語用學」here中給出。

volatile提供了發生之前的邊緣,使得在setter之前發生的所有變化都可見,假設getter實際上觀察到了set值。​​另外另外給出互斥,那volatile不保證單獨。

+0

你是什麼意思*「假設吸氣劑實際觀察到設定值」*。這是否意味着OP中提供的代碼不安全?注:我認爲,在併發性方面我是一種新手,在深入挖掘之前需要熟悉一些基本概念。無論如何感謝您的詳細信息。我必須研究它。 – artaxerxe 2015-04-07 14:23:48

+0

你是什麼意思的「揮發性提供了發生之前的邊緣,以便在setter之前進行更改,在getter之後發生的所有事情都可見」?你是否假定執行setter的特定順序 - > getter? 「在setter之前改變」是什麼意思? – Chin 2017-05-09 13:37:21

+0

對這兩個問題的回答:「假設吸氣劑實際觀察到設定值」在這裏是關鍵。 * IF * getter觀察到由setter設置的值,則setter之前的所有操作都發生在getter之後的任何操作之前。沒有什麼假定這裏的「執行順序」,JMM只說*如果* volatile讀取的是由volatile寫入設置的值,則會在before(通過synchronizes-with)出現。 – 2017-05-09 18:47:07