Go 線程同步
線程同步
通常在 Go 語言中有兩種方法可以用來做線程同步
-
sync.Cond
-
channel
channel 的很好理解,當我們從一個 channel 中接收數據的時候,如果裏面沒有數據,那我們直接就阻塞在那裏了;在這篇文章中就來看看怎麼使用 sync.Cond 完成同步
sync.Cond
「定義結構體和方法」
type BlueberryInt struct {
num int
lock sync.Mutex
cond *sync.Cond
}
func NewBlueberryInt() *BlueberryInt {
// 創建 BlueberryInt 結構體
var obj BlueberryInt
obj.num = 0
obj.cond = sync.NewCond(&obj.lock) // 使用結構體中的 lock 作爲鎖
return &obj // 返回該結構體的指針
}
func (b *BlueberryInt) IncreaseLocked() {
// IncreaseLocked 意味着在做加法操作的時候這個函數需要上鎖後才能使用
b.num++
}
func (b *BlueberryInt) DecreaseLocked() {
// IncreaseLocked 意味着在做減法操作的時候這個函數需要上鎖後才能使用
b.num--
}
func (b *BlueberryInt) Signal() {
// 當完成一件事情後,我們就發送 Signal
b.cond.Signal()
}
func (b *BlueberryInt) Wait() {
// 當我們調用 Wait 的時候,我們還不能馬上執行操作
// 我們需要收到 Signal 後 纔可以繼續執行
b.cond.Wait()
}
func (b *BlueberryInt) Lock() {
// 上鎖
b.lock.Lock()
}
func (b *BlueberryInt) UnLock() {
// 解鎖
b.lock.Unlock()
}
「主要邏輯」
我們分別做 1000 次加法和 1000 次減法,但是呢,我們先讓做減法的 goroutine 運行起來,並且使用 Sleep
等待 1 秒鐘,確保它已經跑起來了;如果我們沒有使用 sync.Cond
的話,這時候減法操作拿到鎖之後就可以直接完成 1000 次的減法了,但是我們調用了 num.Wait()
來等待信號
爲什麼我們在做減法的 goroutine 中已經使用了 num.Lock
之後,在做加法的 goroutine 中還能夠獲得鎖呢?這就是因爲我們在 NewBlueberryInt
中的這行代碼 obj.cond = sync.NewCond(&obj.lock)
,但我們調用 Wait
的時候,它會先釋放我們傳入的那把鎖並且阻塞在那裏,然後等待信號的到來,當它收到信號之後重新獲取那把鎖然後再繼續執行操作
func main() {
// 做了加法才能做減法
b := NewBlueberryInt()
fmt.Printf("the num b is %d \n", b.num)
// 做減法 1000 次
go func(num *BlueberryInt) {
num.Lock()
num.Wait() // 等待信號
for i := 0; i < 1000; i++ {
num.DecreaseLocked()
}
num.UnLock()
}(b)
time.Sleep(time.Second)
// 做加法 1000 次
go func(num *BlueberryInt) {
num.Lock()
for i := 0; i < 1000; i++ {
num.IncreaseLocked()
}
num.Signal() // 發送信號
num.UnLock() // 一定要記得釋放鎖,不然做減法的 goroutine 那裏就永遠走不動了
}(b)
time.Sleep(time.Second)
b.Lock()
fmt.Printf("the num b is %d \n", b.num)
b.UnLock()
}
最後的輸出結果就是這樣的:
the num b is 0
the num b is 0
我是:藍莓,**做個酷的人,過完一生 :)
**微信:點擊我的公衆號底部聯繫我按鈕
強烈推薦加入我的星球 ~
知識星球:酷酷的算法(免費)
星球號:58799376
GitHub:https://github.com/teenager-lijh
小紅書:2133670884
B 站:公衆號同名
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/vk5weMM3kFsX5H6C10GSjQ