Preface
WaitGroup is used in the go language for thread synchronization. It is understood from the literal meaning. WaitGroup means waiting, group group and team. WaitGroup means waiting for a group and waiting for a series to be executed before it continues to be executed downward. WaitGroup in Golang has always been a recommended practice for synchronizing goroutines. I have not encountered any problems after using it for more than two years.
Until recently a colleague threw a strange piece of code over:
The first pit
package main
import (
"log"
"sync"
)
func main() {
wg := {}
for i := 0; i < 5; i++ {
go func(wg , i int) {
(1)
("i:%d", i)
()
}(wg, i)
}
()
("exit")
}
I glanced at it and felt that there was no problem.
However, its running result is like this:
2016/11/27 15:12:36 exit
[Finished in 0.7s]
Or this:
2016/11/27 15:21:51 i:2
2016/11/27 15:21:51 exit
[Finished in 0.8s]
Or this:
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]
It made me think that the mac on my hand didn't wake up...
This question is very easy to fix if you understand the design purpose of WaitGroup. Because WaitGroup synchronizes goroutine, the above code is performed in goroutineAdd(1)
operate. Therefore, it may not be too late for these goroutines Add(1)
Wait operation has been performed.
So the code was changed to this:
The second pit
package main
import (
"log"
"sync"
)
func main() {
wg := {}
for i := 0; i < 5; i++ {
(1)
go func(wg , i int) {
("i:%d", i)
()
}(wg, i)
}
()
("exit")
}
However, the mac fell asleep again, and died of sleep:
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 passes the copy to the goroutine, resulting in only the Add operation. In fact, the Done operation is executed in the copy of wg. So Wait is deadlocked.
So the code was changed to this:
Fill the pit
package main
import (
"log"
"sync"
)
func main() {
wg := &{}
for i := 0; i < 5; i++ {
(1)
go func(wg *, i int) {
("i:%d", i)
()
}(wg, i)
}
()
("exit")
}
Summarize
Okay, here we finally solved it. The above are some pitfalls that need to be paid attention to when using the Go language WaitGroup. I hope the problems mentioned in this article will be helpful to everyone when learning or using the Go language. If you have any questions, you can leave a message to communicate.