Goroutines 是 Go 中并发编程的基本概念。它们允许您同时执行多个任务,而不会阻塞主线程。然而,使用 goroutine 可能会很棘手,尤其是在从多个 goroutine 收集结果时。
问题陈述
一位开发人员尝试使用 goroutine 来处理一系列items 并将处理后的值收集到切片中。然而,他们遇到了可怕的“所有 goroutine 都在睡觉——死锁!”错误。
死锁的根本原因
发生死锁是因为代码在尝试收集结果之前等待所有 goroutine 完成处理。这就造成了这样一种情况:goroutine 正在等待切片可供写入,而主线程正在等待 goroutine 完成处理。
解决方案
为了解决死锁,需要引入异步关闭用于goroutine和主线程之间通信的通道。下面修改后的代码显示了解决方案:
// ... // Create a channel to receive the processed values sampleChan := make(chan sample) var wg sync.WaitGroup // Process each item in the list with a goroutine for i, line := range contents { wg.Add(1) go func(line string) { defer wg.Done() // Process the item and send the result on the channel sampleChan <- newSample(line, *replicatePtr, *timePtr) }(line) } // Asyncronously close the channel when all goroutines are done go func() { wg.Wait() close(sampleChan) }() // Read from the channel and gather results into a slice var sampleList []sample for s := range sampleChan { sampleList = append(sampleList, s) } // ...
通过异步关闭通道,即使 goroutine 仍在处理,主线程也可以继续收集结果。这打破了死锁,让代码能够正确执行。
其他注意事项
值得注意的是,虽然这个解决方案解决了死锁,但它并不是一个完整的解决方案用于管理此特定场景中的并发性。根据需求和 goroutine 的数量,可能需要额外的同步和错误处理机制来确保代码的可靠性和正确性。
以上是从 Go 中的 Goroutine 收集结果时如何避免死锁?的详细内容。更多信息请关注PHP中文网其他相关文章!