持有锁直到所有 goroutines 完成
hold a lock until all goroutines finishes
下面是一段用 Go 编写的代码,取自 Raft Locking Advice,规则 5:
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
.
文章提出的解决方案如下:
One way to fix this is for the created goroutine to
use a copy of rf.currentTerm made while the outer code holds the lock.
但我不是很清楚它是什么意思。
您可以将参数传递给 go 例程函数,例如:
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()
在不了解您要完成的目标的情况下,我不确定这是最佳解决方案。
下面是一段用 Go 编写的代码,取自 Raft Locking Advice,规则 5:
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
.
文章提出的解决方案如下:
One way to fix this is for the created goroutine to use a copy of rf.currentTerm made while the outer code holds the lock.
但我不是很清楚它是什么意思。
您可以将参数传递给 go 例程函数,例如:
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()
在不了解您要完成的目标的情况下,我不确定这是最佳解决方案。