> For the complete documentation index, see [llms.txt](https://hantmac.gitbook.io/mastering-go-second/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hantmac.gitbook.io/mastering-go-second/09.0/09.3/09.3.1.md).

# 09.3.1 当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`)可能并不总是出现。
