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...