3 回答

TA貢獻1765條經(jīng)驗 獲得超5個贊
請記住,除非您是手動編寫程序集,否則您不是在編程到機器的內(nèi)存模型,而是在編程到Go的內(nèi)存模型。這意味著,即使原始賦值與您的架構(gòu)是原子的,Go也需要使用原子包來確保所有支持的架構(gòu)的正確性。
對互斥鎖外部標志的訪問只需要是安全的,而不是嚴格排序的,因此可以使用原子操作,而不是總是使用互斥鎖獲取鎖。這是一種優(yōu)化,使快速路徑盡可能高效,允許在熱路徑中使用。done
sync.Once
用于 的互斥體僅用于該函數(shù)內(nèi)的互斥,以確保在設置標志之前只有一個調(diào)用方能夠進入該函數(shù)。該標志是使用 編寫的,因為它可能與受互斥鎖保護的關(guān)鍵部分之外同時發(fā)生。doSlow
f()
done
atomic.StoreUint32
atomic.LoadUint32
在寫入的同時讀取字段,甚至是原子寫入,也是一場數(shù)據(jù)競賽。僅僅因為字段是原子讀取的,并不意味著您可以使用正常的賦值來寫入它,因此首先檢查標志并編寫done
atomic.LoadUint32
atomic.StoreUint32
對 within 的直接讀取是安全的,因為它受到互斥鎖的并發(fā)寫入保護。同時讀取值是安全的,因為兩者都是讀取操作。done
doSlow
atomic.LoadUint32

TA貢獻1818條經(jīng)驗 獲得超3個贊
原子操作可用于同步不同 goroutine 的執(zhí)行。
如果沒有同步,即使 goroutine 觀察到 o.done == 1,也不能保證它會觀察到 的效果。f()

TA貢獻1966條經(jīng)驗 獲得超4個贊
func (o *Once) Do(f func()) {
if atomic.LoadUint32(&o.done) == 0 { # 1
// Outlined slow-path to allow inlining of the fast-path.
o.doSlow(f)
}
}
func (o *Once) doSlow(f func()) {
o.m.Lock()
defer o.m.Unlock()
if o.done == 0 { # 2
defer atomic.StoreUint32(&o.done, 1) # 3
f()
}
}
#1和#3:#1是讀的,#3是寫的,它不安全,需要mutext來保護
#2和#3 :在關(guān)鍵部分,由互斥體支持,安全。
- 3 回答
- 0 關(guān)注
- 142 瀏覽
添加回答
舉報