2 回答

TA貢獻1830條經(jīng)驗 獲得超9個贊
這是競爭條件的經(jīng)典例子。value++
不是原子操作,因此無法保證在沒有同步的情況下從多個線程調用時它會正確或確定地工作。
給出一些直覺,value++
或多或少等同于value = value + 1
. 您可以將其視為三個操作,而不是一個:value
從內存加載到 CPU 寄存器,增加寄存器中的值(您不能直接修改內存),將值存儲回內存。兩個線程可能同時加載相同的值,增加它,得到相同的結果,然后將它寫回,所以它實際上增加了value
1,而不是兩個。
由于線程之間的操作順序是不確定的,因此結果也是不確定的。
同樣的效果發(fā)生在totalOps
. 但是,totalIncOps
和totalDecOps
只能由單個線程修改/讀取,因此這里沒有競爭,它們的最終值是確定性的。

TA貢獻1818條經(jīng)驗 獲得超8個贊
因為對變量 value、totalOps、totalIncOps 和 totalDecOps 的操作沒有被鎖定
添加互斥鎖應該有所幫助。Go race detector 功能會發(fā)現(xiàn)這個錯誤
var m sync.Mutex
func increaseByOne(N int, waitGroup *sync.WaitGroup) {
for i := 0; i < N; i++ {
m.Lock()
value++
// Collecting stats
totalOps++
totalIncOps++
m.Unlock()
}
waitGroup.Done()
}
// Same with decrease
func decreaseByOne(N int, waitGroup *sync.WaitGroup) {
for i := 0; i < N; i++ {
m.Lock()
value--
// Collecting stats
totalOps++
totalDecOps++
m.Unlock()
}
waitGroup.Done()
}
上述方法的替代方法是對計數(shù)器使用 Sync.Atomic
- 2 回答
- 0 關注
- 171 瀏覽
添加回答
舉報