[英]compareAndSwap a common member ( non-volatile member ) still has memory semantics of volatile read and write
當我在 jdk1.8 中閱讀AbstractQueuedSynchronizer
時,我看到compareAndSetState
方法具有易失性讀寫的內存語義的評論。
注釋和代碼如下:
/**
* Atomically sets synchronization state to the given updated
* value if the current state value equals the expected value.
* This operation has memory semantics of a {@code volatile} read
* and write.
*/
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
在 AbstractQueuedSynchronizer 類中, stateOffset
是一個名為state
的 volatile 成員
只是想知道如果state
是非易失性成員,內存語義是什么......
compareAndSetState()
的語義仍然是 volatile 讀寫的語義——這是Unsafe.compareAndSwapInt()
存在的主要原因。
但通常代碼不僅僅調用Unsafe.compareAndSwapInt()
。 通常代碼讀取當前值,計算一個新值,然后嘗試用新值替換它讀取的值。 而且這種讀取也必須使用易失性讀取語義來完成。
例如,在CountDownLatch.Sync#tryReleaseShared()
中:
protected boolean tryReleaseShared(int releases) { // Decrement count; signal when transition to zero for (;;) { int c = getState(); if (c == 0) return false; int nextc = c-1; if (compareAndSetState(c, nextc)) return nextc == 0; } }
使用getState()
讀取state
必須使用 volatile 讀取語義,以確保它使用最新值。
是的,原則上你可以拒絕將state
這樣的字段聲明為 volatile。 但是你必須確保對該字段的每次訪問都通過compareAndSwapInt()
、 getIntVolatile()
和putIntVolatile()
。 如果代碼的某些維護者忘記了此規則並添加了對該字段的單次直接讀取,您的代碼將在最不利的時刻以意想不到的方式中斷 - 例如,在向重要客戶進行演示時。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.