版权声明:本文为博主原创文章,转载时请务必注明本文地址, 禁止用于任何商业用途, 否则会用法律维权。 https://blog.csdn.net/stpeace/article/details/83921198
看程序:
package main
import (
"fmt"
"time"
)
func print(i int) {
time.Sleep(1e9)
fmt.Println(i)
}
func main() {
for i := 0; i < 10; i++ {
go func(n int) {
print(n)
}(i)
}
}
结果没有任何输出,因为主协程很快退出了。
等待一下,变为:
package main
import (
"fmt"
"time"
)
func print(i int) {
time.Sleep(1e9)
fmt.Println(i)
}
func main() {
for i := 0; i < 10; i++ {
go func(n int) {
print(n)
}(i)
}
for {}
}
结果:
7
9
3
4
5
8
0
6
1
2
这种等待太傻了, 改为:
package main
import (
"fmt"
"sync"
"time"
)
func print(i int) {
time.Sleep(1e9)
fmt.Println(i)
}
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(n int) {
defer wg.Add(-1) // same: defer wg.Done()
print(n)
}(i)
}
wg.Wait()
}
结果:
8
1
5
0
9
4
7
2
6
3
分析一下wg.Wait执行等待操作, 直到wg的计数变为0才返回。 在上面例子中,Add(1)了10次, 然后Add(-1)了10次,刚好。 我们把程序变一下:
package main
import (
"fmt"
"sync"
"time"
)
func print(i int) {
time.Sleep(1e9)
fmt.Println(i)
}
func main() {
var wg sync.WaitGroup
wg.Add(11)
for i := 0; i < 10; i++ {
go func(n int) {
defer wg.Add(-1) // same: defer wg.Done()
print(n)
}(i)
}
wg.Wait()
}
可以看到,计数达到11次,但只有10次的add(-1), 显然wg.Wait永远无法退出,提示:fatal error: all goroutines are asleep - deadlock!
再看:
package main
import (
"fmt"
"sync"
"time"
)
func print(i int) {
time.Sleep(1e9)
fmt.Println(i)
}
func main() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 10; i++ {
go func(n int) {
defer wg.Add(-1) // same: defer wg.Done()
print(n)
}(i)
}
wg.Wait()
}
结果出错,提示信息:
panic: sync: WaitGroup is reused before previous Wait has returned
panic: sync: negative WaitGroup counter
看到没, negative counter了。
不多说。