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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hantmac.gitbook.io/mastering-go-second/09.0/09.3/09.3.1.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
