sync.once
能夠控制函數只能被調用一次。不能屢次重複調用。函數
例如:保證channel 關閉只執行一次,避免關閉已關閉的channel致使panic線程
type MyChannel struct { C chan T once sync.Once } func NewMyChannel() *MyChannel { return &MyChannel{C: make(chan T)} } func (mc *MyChannel) SafeClose() { mc.once.Do(func(){ close(mc.C) }) }
更多的實現原理,參考:https://cloud.tencent.com/dev...code
sync.Mutex
互斥鎖
它可以保證同時只有一個 goroutine 能夠訪問到共享資源(同一個時刻只有一個線程可以拿到鎖)
1.Lock() 加鎖,Unlock() 解鎖
2.在一個 goroutine 得到 Mutex 後,其餘 goroutine 只能等到這個 goroutine 釋放該 Mutex(阻塞住)
3.在同一個 goroutine 中的 Mutex 解鎖以前再次進行加鎖,會致使死鎖(fatal error: all goroutines are asleep - deadlock!)
4.已經鎖定的 Mutex 並不與特定的 goroutine 相關聯,這樣能夠利用一個 goroutine 對其加鎖,再利用其餘 goroutine 對其解鎖資源
sync.RWMutex
讀寫鎖
1.Lock() 加寫鎖,Unlock() 解寫鎖
2.RLock() 加讀鎖,RUnlock() 解讀鎖
3.RLock() 加讀鎖時,若是存在寫鎖,則沒法加讀鎖;當只有讀鎖或者沒有鎖時,能夠加讀鎖,讀鎖能夠加載多個
4.若是在加寫鎖以前已經有其餘的讀鎖和寫鎖,則 Lock() 會阻塞直到該鎖可用,爲確保該鎖可用,已經阻塞的 Lock() 調用會從得到的鎖中排除新的讀取器,即寫鎖權限高於讀鎖,有寫鎖時優先進行寫鎖定get