企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# **当Add()和Done()的数量不匹配时会发生什么?** 当`sync.Add()`和`sync.Done()`调用的数量相等时,程序会正常运行。但是,本节将告诉你当调用数量不一致时会发生什么。 假如我们执行`sync.Add()`的次数大于执行`sync.Done()`的次数,这种情况下,通过在第一个`fmt.Printf(“%#v \ n”,waitGroup)`之前添加`waitGroup.Add(1)`语句,然后执行go run的输出如下: ```bash $ go run syncGo.go Going to create 20 goroutines. sync.WaitGroup{noCopy:sync.noCopy{}, state1:[12]uint8{0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, sema:0x0} sync.WaitGroup{noCopy:sync.noCopy{}, state1:[12]uint8{0x0, 0x0, 0x0, 0x0, 0x15, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, sema:0x0} 19 10 11 12 13 17 18 8 5 4 6 14 1 0 7 3 2 15 9 16 fatal error: all goroutines are asleep - deadlock! goroutine 1 [semacquire]: sync.runtime_Semacquire(0xc4200120bc) /usr/local/Cellar/go/1.9.3/libexec/src/runtime/sema.go:56 +0x39 sync.(*WaitGroup).Wait(0xc4200120b0) /usr/local/Cellar/go/1.9.3/libexec/src/sync/waitgroup.go:131 +0x72 main.main() /Users/mtsouk/Desktop/masterGo/ch/ch9/code/syncGo.go:28 +0x2d7 exit status 2 ``` 错误消息是很清楚的: `fatal error: all goroutines are asleep - deadlock!`.,这是因为你通过调用`sync.Add(1)`函数`n+1`次来告诉程序等待`n+1`个`goroutine`,而`n`个`goroutine`只执行了`n`个`sync.Done()`语句。因此,`sync.Wait()`调用将无限期地等待一个或多个对`sync.Done()`的调用,而不会有任何结果,这显然是死锁的情况。 如果使用的`sync.Add()`调用比`sync.Done()`调用少,那么可以通过在`syncGo.go`的for循环之后添加waitGroup.Done()语句来进行模拟。那么执行后输出类似如下的结果: ```bash $ go run syncGo.go Going to create 20 goroutines. sync.WaitGroup{noCopy:sync.noCopy{}, state1:[12]uint8{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, sema:0x0} sync.WaitGroup{noCopy:sync.noCopy{}, state1:[12]uint8{0x0, 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, sema:0x0} 19 6 1 2 9 7 8 15 13 0 14 16 17 3 11 4 5 12 18 10 panic: sync: negative WaitGroup counter goroutine 22 [running]: sync.(*WaitGroup).Add(0xc4200120b0, 0xffffffffffffffff) /usr/local/Cellar/go/1.9.3/libexec/src/sync/waitgroup.go:75 +0x134 sync.(*WaitGroup).Done(0xc4200120b0) /usr/local/Cellar/go/1.9.3/libexec/src/sync/waitgroup.go:100 +0x34 main.main.func1(0xc4200120b0, 0x11) /Users/mtsouk/Desktop/masterGo/ch/ch9/code/syncGo.go:25 +0xd8 created by main.main /Users/mtsouk/Desktop/masterGo/ch/ch9/code/syncGo.go:21 +0x206 exit status 2 ``` 这次问题的根源也非常清楚:`panic: sync: negative WaitGroup counter`。虽然这两种情况下的错误消息都非常具体,可以帮助你解决实际的问题,但是你应该非常小心地处理放入程序中的`sync.Add()`和`sync.Done()`调用的数量。另外,请注意,第二个错误情况(`panic: sync: negative WaitGroup counter`)可能并不总是出现。