go - 使用互斥锁 - 仍然是死锁
问题描述
我正在玩 Goroutine 和通道,想知道为什么我在标题中出现错误。
这个想法是我有一个全局 int 通道,每个路由都会递增。
通过使用互斥锁,我希望每个例程都会锁定通道,但失败了。
代码在这里:
package main
import (
"fmt"
"sync"
)
var number = make(chan int)
var mutex = &sync.Mutex{}
func worker(wg *sync.WaitGroup, id int) {
defer wg.Done()
mutex.Lock()
number <- id + <-number
mutex.Unlock()
}
func main() {
var wg sync.WaitGroup
number <- 0
for i := 0; i < 5; i++ {
wg.Add(1)
go worker(&wg, i)
}
wg.Wait()
fmt.Println(<-number) // expected output: 0+1+2+3+4 = 10
}
解决方案
这里的问题与您正在使用的通道有关,因为它是无缓冲的。一个无缓冲的通道将阻塞,直到有接收者接收消息。
在这里,主 go 例程向通道添加一个数字,然后创建 5 个 go 例程来移除通道并添加到通道,然后等待它们完成,然后再从通道中移除一个项目。在有东西从它接收数字之前,不会向通道添加 0,因此它甚至在到达互斥体之前就被阻塞了。
这 5 个 go 例程只有在有东西从频道中取出时才能完成。
如果您通过向 make 调用提供大小来更改为缓冲通道,那么这将开始运行到完成:
package main
import (
"fmt"
"sync"
)
var number = make(chan int, 5)
var mutex = &sync.Mutex{}
func worker(wg *sync.WaitGroup, id int) {
defer wg.Done()
mutex.Lock()
number <- id + <-number
mutex.Unlock()
}
func main() {
var wg sync.WaitGroup
number <- 0
for i := 0; i < 5; i++ {
wg.Add(1)
go worker(&wg, i)
}
wg.Wait()
fmt.Println(<-number) // expected output: 0+1+2+3+4 = 10
}
推荐阅读
- angular - 如何在agGrid中隐藏单元格工具提示?
- c++ - 如何在 C++ 中以这种方式返回一行文本?
- bash - 根据 SSID 更改 MacOS 位置 - 无法让脚本自动运行
- ios - 在连接的设备上构建和运行带有 Firebase 框架错误的 swiftUI ios 应用程序的修复方法是什么?
- python - Flask-Uploads:如何按内容强制文件类型(不仅仅是扩展名)
- c++ - 从 cin 读取不会返回整个输入字符串
- python - Pygame 显示不更新
- c# - 如何在 Fact 测试方法中获取 xUnit Fact Attribute 'DisplayName' 参数
- sass - 如何使用汇总从 @material 导入 scss 文件?
- ios - xcode ios - 每当调整滑块时更新预定计时器