Par*_*hah 3 multithreading synchronization go
我遇到的情况是,主要的 go 例程将创建“x”个 go 例程。但它只对要完成的“y”( y < x ) go 例程感兴趣。
我本来希望使用 Waitgroup。但 Waitgroup 只允许我等待所有 go 例程。例如,我不能这样做,
1. wg.Add (y)
2 create "x" go routines. These routines will call wg.Done() when finished.
3. wg. Wait()
Run Code Online (Sandbox Code Playgroud)
当 y+1 go 例程调用 wg.Done() 时,会出现恐慌,因为 wg 计数器变为负值。
我当然可以使用渠道来解决这个问题,但我对 Waitgroup 是否能解决这个问题感兴趣。
正如Adrian 的回答中所述,sync.WaitGroup是一个简单的计数器,其Wait方法将阻塞,直到计数器值达到零。它的目的是允许您在允许主执行流程继续之前阻止(或加入)多个 goroutine。
的界面WaitGroup对于您的用例来说没有足够的表现力,也不是这样设计的。特别是,您不能通过简单地调用wg.Add(y)(where y < x) 来使用它 na\xc3\xafvely。wg.Done第 (y+1)个goroutine 的调用将导致恐慌,因为等待组具有负内部值是一个错误。此外,我们不能通过观察内部计数器值来“聪明”。WaitGroup;这会破坏抽象,并且无论如何,其内部状态都不会被导出。
您可以根据下面的代码使用一些通道自行实现相关逻辑(游乐场链接)。从控制台观察到,有 10 个 goroutine 启动了,但在两个完成后,我们就在 main 方法中继续执行。
\n\npackage main\n\nimport (\n "fmt"\n "time"\n)\n\n// Set goroutine counts here\nconst (\n // The number of goroutines to spawn\n x = 10\n // The number of goroutines to wait for completion\n // (y <= x) must hold.\n y = 2\n)\n\nfunc doSomeWork() {\n // do something meaningful\n time.Sleep(time.Second)\n}\n\nfunc main() {\n // Accumulator channel, used by each goroutine to signal completion.\n // It is buffered to ensure the [y+1, ..., x) goroutines do not block\n // when sending to the channel, which would cause a leak. It will be\n // garbage collected when all goroutines end and the channel falls\n // out of scope. We receive y values, so only need capacity to receive\n // (x-y) remaining values.\n accChan := make(chan struct{}, x-y)\n\n // Spawn "x" goroutines\n for i := 0; i < x; i += 1 {\n // Wrap our work function with the local signalling logic\n go func(id int, doneChan chan<- struct{}) {\n fmt.Printf("starting goroutine #%d\\n", id)\n doSomeWork()\n fmt.Printf("goroutine #%d completed\\n", id)\n\n // Communicate completion of goroutine\n doneChan <- struct{}{}\n }(i, accChan)\n }\n\n for doneCount := 0; doneCount < y; doneCount += 1 {\n <-accChan\n }\n\n // Continue working\n fmt.Println("Carrying on without waiting for more goroutines")\n}\nRun Code Online (Sandbox Code Playgroud)\n\n由于这不会等待 [y+1, ..., x) goroutine 完成,因此您应该在函数中特别小心,doSomeWork以消除或最小化工作无限期阻塞的风险,这也会导致泄漏。尽可能消除无限期阻塞 I/O(包括通道操作)或陷入无限循环的可能性。
context当不再需要额外的 goroutine 的结果来让它们退出执行时,您可以使用 a向它们发出信号。
| 归档时间: |
|
| 查看次数: |
1742 次 |
| 最近记录: |