前言:為了保證并發(fā)安全,go語言中可以使用原子操作黍特。其執(zhí)行過程不能被中斷触创,這也就保證了同一時刻一個線程的執(zhí)行不會被其他線程中斷,也保證了多線程下數(shù)據(jù)操作的一致性候醒。
1.sync/atomic包
2.Load和Store并發(fā)不安全
1.sync/atomic包
在atomic包中對幾種基礎(chǔ)類型提供了原子操作能颁,包括int32,int64倒淫,uint32伙菊,uint64,uintptr敌土,unsafe.Pointer镜硕。
對于每一種類型,提供了五類原子操作分別是
- Add, 增加和減少
- CompareAndSwap, 比較并交換
- Swap, 交換
- Load , 讀取
- Store, 存儲
2.Load和Store并發(fā)不安全
Load和Store操作對應(yīng)與變量的原子性讀寫返干,許多變量的讀寫無法在一個時鐘周期內(nèi)完成谦疾,而此時執(zhí)行可能會被調(diào)度到其他線程,無法保證并發(fā)安全犬金。
??Load 只保證讀取的不是正在寫入的值念恍,Store只保證寫入是原子操作六剥。
所以在使用的時候要注意。
下面簡單示例:
package main
import (
"sync"
"sync/atomic"
"fmt"
)
var (
wg sync.WaitGroup
mu sync.Mutex
num int32
)
func wrap(callback func()) {
wg.Add(1)
go func() {
callback()
wg.Done()
}()
}
// go build -race
func main() {
// 1099 峰伙、892, 并發(fā)不安全
//wrap(incNumAtomic)
//wrap(incNumAtomic)
// 1200, 并發(fā)安全
wrap(incNumAtomic2)
wrap(incNumAtomic2)
wg.Wait()
fmt.Printf("num=%d\n", num)
}
func incNumAtomic() {
for i := 0; i < 600; i++ {
// atomic.Load*系列函數(shù)只能保證讀取的不是正在寫入的值(比如只被修改了一半的數(shù)據(jù))
// 同樣的atomic.Store* 只保證寫入是原子操作(保證寫入操作的完整性)
val := atomic.LoadInt32(&num)
atomic.StoreInt32(&num, val+1)
}
}
func incNumAtomic2() {
for i := 0; i < 600; i++ {
atomic.AddInt32(&num, 1)
}
}
總結(jié)
點擊??查看源碼疗疟,哈哈哈...