學習golang之同步原語sync包

2021-10-16 10:24:44 字數 2794 閱讀 3996

資源競爭

以上被加鎖保護的 sum+=i **片段又稱為臨界區。

這個示例開啟了 10 個協程,它們同時讀取 sum 的值。因為 readsum 函式並沒有任何加鎖控制,所以它不是併發安全的,即乙個 goroutine 正在執行 sum+=i 操作的時候,另乙個 goroutine 可能正在執行 b:=sum 操作,這就會導致讀取的 num 值是乙個過期的值,結果不可預期。

如果要解決以上資源競爭的問題,可以使用互斥鎖 sync.mutex,那麼有沒有辦法監聽所有協程的執行,一旦全部執行完畢,程式馬上退出,go 提供了更簡潔的解決辦法,它就是 sync.waitgroup

//共享的資源

var(

sum int

mutex sync.mutex

mutexr sync.rwmutex

)func

add(i int

)func

run()(

)}for i:=

0; i<

10;i++()

}//一直等待,只要計數器值為0

wg.wait()

}func

main()

//增加了乙個讀取sum的函式,便於演示併發

func

readsum()

int

sync.waitgroup 一共分為三步:

宣告乙個 sync.waitgroup,然後通過 add 方法設定計數器的值,需要跟蹤多少個協程就設定多少,這裡是 110

在每個協程執行完畢時呼叫 done 方法,讓計數器減 1,告訴 sync.waitgroup 該協程已經執行完畢

最後呼叫 wait 方法一直等待,直到計數器值為 0,也就是所有跟蹤的協程都執行完畢

func

main()

func

doonce()

//用於等待協程執行完畢

done :=

make

(chan

bool

)//啟動10個協程執行once.do(oncebody)

for i :=

0; i <

10; i++()

}for i :=

0; i <

10; i++

}

10 個協程來執行 oncebody 函式,但是因為用了 once.do 方法,所以函式 oncebody 只會被執行一次。也就是說在高併發的情況下,sync.once 也會保證 oncebody 函式只執行一次。

//10個人賽跑,1個裁判發號施令

func

race()

)var wg sync.waitgroup

wg.add(11)

for i:=

0;i<

10; i++

(i)}

//等待所有goroutine都進入wait狀態

time.

sleep(2

*time.second)

gofunc()

()//防止函式提前返回退出

wg.wait()

}

在 go 語言中,sync.waitgroup 用於最終完成的場景,關鍵點在於一定要等待所有協程都執行完畢。而 sync.cond 可以用於發號施令,一聲令下所有協程都可以開始執行,關鍵點在於協程開始的時候是等待的,要等待 sync.cond 喚醒才能執行。

通過 sync.newcond 函式生成乙個 *sync.cond,用於阻塞和喚醒協程

然後啟動 10 個協程模擬 10 個人,準備就位後呼叫 cond.wait() 方法阻塞當前協程等待發令槍響,這裡需要注意的是呼叫 cond.wait() 方法時要加鎖

time.sleep 用於等待所有人都進入 wait 阻塞狀態,這樣裁判才能呼叫 cond.broadcast() 發號施令

裁判準備完畢後,就可以呼叫 cond.broadcast() 通知所有人開始跑了

sync.cond 有三個方法,它們分別是:

1.wait,阻塞當前協程,直到被其他協程呼叫 broadcast 或者 signal 方法喚醒,使用時需要加鎖,使用 sync.cond 中的鎖即可,也就是 l 字段。

2.signal,喚醒乙個等待時間最長的協程。

3.broadcast,喚醒所有等待的協程。

注意:在呼叫 signal 或者 broadcast 之前,要確保目標協程處於 wait 阻塞狀態,不然會出現死鎖問題。
func

race()

)var wg sync.waitgroup

wg.add(11)

for i:=

0;i<

10; i++

(i)}

//等待所有goroutine都進入wait狀態

time.

sleep(2

*time.second)

gofunc()

()//防止函式提前返回退出

wg.wait()

}

golang同步機制之通道

1.通道是什麼 通道,在golang中的形式為型別為chan,是golang中同步的兩個機制之一 另乙個是waitgroup chan的語法形式如下 channeltype chan chan chan elementtype chan的型別可以是chan chan chan任意一種 資料型別 如i...

golang學習之安裝環境

安裝 1.官網安裝最新的golang安裝包 配置環境變數 export goroot home go export path path goroot bin 再配置gopath,路徑為gopath d gopath gopath主要用於第三方包存放目錄src下 個人理解 3.開啟liteide執行h...

golang學習之html json解析

golang解析html檔案 由於專案中需要用到json,使用的是 步驟很簡單 1.連線url獲取頁面內容 2.將頁面內容轉換成json 3.解析json,列印到控制台 很簡單如下,直接執行就可以 inte ce的強制型別轉換 func prase m1 inte ce wei weidata da...