我有這種情況,我有一個狀態變量; INT狀態=(2,1,0) 和無限循環:在這些條件下設置變量原子
ret = BoolCompareAndSwap(state, 1, 2)
if (ret) {
// Change something ...
state = 0;
}
這會狀態設置是原子? 假設設置一個變量,你必須:
- 從內存
- 變化值
- 設置新的價值
取出如果其他線程來比較變量,它會是原子的,因爲直到它重新設置在內存中,實際值纔會改變,是否正確?
我有這種情況,我有一個狀態變量; INT狀態=(2,1,0) 和無限循環:在這些條件下設置變量原子
ret = BoolCompareAndSwap(state, 1, 2)
if (ret) {
// Change something ...
state = 0;
}
這會狀態設置是原子? 假設設置一個變量,你必須:
- 從內存
- 變化值
- 設置新的價值
取出如果其他線程來比較變量,它會是原子的,因爲直到它重新設置在內存中,實際值纔會改變,是否正確?
嚴格來說,如果C編譯器按位寫入狀態,它們仍然是標準符合。在寫入前幾位後,其他一些線程可以讀取任何類型的垃圾。
大多數編譯器都沒有這樣的事情(除了古代4位處理器的編譯器可能例外,甚至更窄......),因爲這會導致性能下降。
而且,和更實際的相關性,如果任何其他線程寫入(而不是僅僅讀出)狀態,即寫入的值可能會丟失,如果你不防範的比賽條件所描述的代碼。
作爲一個側面說明,所描述的狀態改變(讀取,修改,寫入)從來不是原子的。然而,當這種非原子性是脆弱的時候,這個問題是有效的,這正是我上面試圖回答的問題。
更一般地說,思考所有可能的併發訪問組合是一種有效的保護機制。然而,在許多方面(設計工作量,測試工作量,維護期間的風險......)都是非常昂貴的。
只有當這些成本總計小於預期的節省量(可能的性能)時,纔可以這樣做,而不是使用適當的保護機制。
那麼,假設CompareAndSwap不會產生真正的,如果什麼是讀垃圾,並且其他線程只會作用於上述狀態,如果它實際上是0,你可以說狀態變量被保護,它被設置爲中間值?這對我來說最有意義......(如果一個CompareAndSwap(state,0,2)爲true,那麼上述變量只能被其他線程訪問) – Whiteclaws
我無法想象其他線程只會在狀態爲0 。「垃圾」意味着垃圾最終設置爲0.此目標的垃圾可以通過其他有效狀態,垃圾與預期的0相比較,但無法與其他有效值區分。例如有效值0,1,2,3。在兩個步驟中清除3,您可以在操作過程中獲得有效的非零垃圾「2」或「1」。 – Yunnosch
@Whiteclaws更一般地說,思考所有可能的併發訪問組合是一種有效的保護機制。然而,它在很多方面都非常合算(設計工作量,測試工作量,維護期間的風險......)。只有這些成本總體上小於預期的節省量(可能是性能),才能這樣做,而不是採用適當的保護機制。 – Yunnosch
看到這個[問題](https://stackoverflow.com/questions/25319825/how-to-use-atomic-variables-in-c),這是以前問關於原子變量。狀態設置的順序取決於線程是如何完成的,即使線程安全。 – t0mm13b