go - 持有锁直到所有 goroutine 完成
问题描述
下面是一段取自Raft Locking Advice规则 5 的 Go 代码:
rf.mu.Lock()
rf.currentTerm += 1
rf.state = Candidate
for <each peer> {
go func() {
rf.mu.Lock()
args.Term = rf.currentTerm
rf.mu.Unlock()
Call("Raft.RequestVote", &args, ...)
// handle the reply...
} ()
}
rf.mu.Unlock()
Raft 是一些共识算法,rf 指的是 Raft。上面的代码试图做的是一个领导者正在向它的所有对等方发送 RPC 请求,要求投票。正如代码后面的段落所指出的,这段代码并不理想,因为 rf.currentTerm 可能在子例程被触发之前已经被更改。目标是 rf 的状态在其对等节点投票时保持不变。
我的补救措施是使用等待组让代码在最后一个之前等待rf.mu.Unlock
。这肯定会解决提到的问题。然而,建议中的第 4 条规定:it's usually a bad idea to hold a lock while doing anything that might wait
.
文章提出的解决方案如下:
解决此问题的一种方法是创建的 goroutine 使用在外部代码持有锁时制作的 rf.currentTerm 的副本。
但我不太确定这意味着什么。
解决方案
您可以将参数传递给 goroutine 函数,例如:
rf.mu.Lock()
rf.currentTerm += 1
rf.state = Candidate
for <each peer> {
go func(ct CurrentTerm) {
rf.mu.Lock()
args.Term = ct
rf.mu.Unlock()
Call("Raft.RequestVote", &args, ...)
// handle the reply...
} (rt.currentTerm)
}
rf.mu.Unlock()
如果不了解您要完成的工作,我不确定这是最好的解决方案。
推荐阅读
- python - cv2 编辑的图像以错误的颜色保存
- javascript - 使用声纳扫描仪在我的反应项目中意外的令牌 =(在模块模式下使用 espree 解析器)
- asp.net-core - 如何在具有 maxAllowedContentLength 的 IIS 上的 ASP.NET Core 中使用 MaxRequestBodySize?
- node.js - 如何在 nodejs 加密库中设置 aes cfb 反馈段大小?
- vb.net - 添加新列后无法访问 DataGridView 列名
- javascript - 检查给定数字是否是另一个小数的倍数
- sql - 跨数据库表减去常量
- sql - 如何使用 Big Query SQL Standard 将日期 YYYY-MM-DD 转换为字符串 YYYYMM?
- docker - 使用奇异性在snakemake中规则:未终止的带引号的字符串
- angular - 如何将 Aria 标签应用于 PrimeNG 组件的子元素?