Go語言WaitGroup使用時需要注意什麼

2022-09-23 09:03:12 字數 1742 閱讀 8436

go語言waitgroup使用時需要注意什麼?

前言waitgroup在go語言中,用於執行緒同步,單從字面意思理解,wait等待的意思,group組、團隊的意思,waitgroup就是指等待一組,等待乙個系列執行完成後才會繼續向下執行。golang 中的 waitgroup 一直是同步 goroutine 的推薦實踐。自己用了兩年多也沒遇到過什麼問題。

直到最近的一天同事扔過來一段奇怪的**:

第乙個坑

複製** **如下:

package main

import (

"log"

"sync"

) func main()

for i := 0; i < 5; i++ (wg, i)

} wg.wait()

log.println("exit")

}撇了一眼,覺得沒什麼問題。

然而,它的執行結果是這樣:

複製** **如下:

2016/11/27 15:12:36 exit

[finished in 0.7s]

或這樣:

複製** **如下:

2016/11/27 15:21:51 i:2

2016/11/27 15:21:51 exit

[finished in 0.8s]

或這樣:

複製** **如下:

2016/11/27 15:22:51 i:3

2016/11/27 15:22:51 i:2

2016/11/27 15:22:51 exit

[finished in 0.8s]

一度讓我以為手上的 mac 也沒睡醒……

這個問題如果理解了 waitgroup 的設計目的就非常容易 fix 啦。因為 waitgroup 同步的是 goroutine, 而上面的**卻在 goroutine 中進行 add(1) 操作。因此,可能在這些 goroutine 還沒來得及 add(1) 已經執行 wait 操作了。

於是**改成了這樣:

第二個坑

複製** **如下:

package main

import (

"log"

"sync"

func main()

for i := 0; i < 5; i++ (wg, i)

wg.wait()

log.println("exit")

然而,mac 又睡了過去,而且是睡死了過去:

複製** **如下:

2016/11/27 15:25:16 i:1

2016/11/27 15:25:16 i:2

2016/11/27 15:25:16 i:4

2016/11/27 15:25:16 i:0

2016/11/27 15:25:16 i:3

fatal error: all goroutines are asleep - deadlock!

wg 給拷貝傳遞到了 goroutine 中,導致只有 add 操作,其實 done操作是在 wg 的副本執行的。因此 wait 就死鎖了。

於是**改成了這樣:

填坑複製** **如下:

package main

import (

"log"

"sync"

func main()

for i := 0; i < 5; i++ (wg, i)

wg.wait()

log.println("exit")

Go 語言使用WaitGroup個人筆記記錄

func main 下乙個週期時間用來判斷是否是未來時,如果不是未來時間,那麼將查詢時間替換成下乙個週期 nexttime,flag handlenextgranularitytime searchtime,analysisreq.granularity,analysisreq.type searc...

go語言gorm使用

var jsondata map string inte ce 全域性變數 存放配置檔案的map物件 func initjson configstr string bytes reg regexp.mustcompile configstr reg.replaceallstring configst...

go語言使用redis redigo

redis的client有好多好多,go語言的client在redis官方有兩個推薦,radix和redigo。選擇哪乙個好呢?確實很糾結,後來擲硬幣決定選擇redigo了。redis go redigo的安裝就不需要提了,不能強行增加篇幅。redigo使用起來很人性化,api設計的符合直覺,我對r...