Golang中实现互斥锁的Tie-breaker算法遇到问题求助
Golang中实现互斥锁的Tie-breaker算法遇到问题求助

var data int = 1
var done = make(chan bool)
var last int = 1
var in1 bool = false
var in2 bool = false
var mu sync.Mutex
func racing1() {
for i := 0; i < 10000; i++ {
last = 1
in1 = true
for in2 && last == 1 {
}
// mu.Lock()
data = data + 1
// mu.Unlock()
in1 = false
}
done <- true
}
func racing2() {
for i := 0; i < 10000; i++ {
last = 2
in2 = true
for in1 && last == 2 {
}
// mu.Lock()
data = data + 1
// mu.Unlock()
in2 = false
}
done <- true
}
func main() {
go racing1()
go racing2()
<-done
<-done
fmt.Println(data)
}
更多关于Golang中实现互斥锁的Tie-breaker算法遇到问题求助的实战教程也可以访问 https://www.itying.com/category-94-b0.html
3 回复
是的。我已经确认,如果存在数据竞争,常见的编程语言并不能保证顺序一致性。
无论如何,感谢!
更多关于Golang中实现互斥锁的Tie-breaker算法遇到问题求助的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这个代码实现的是Peterson算法,用于两个goroutine之间的互斥访问。问题在于没有正确实现内存可见性保证,导致竞争条件。
主要问题:
- Go的内存模型不保证goroutine间的变量可见性
- 缺少内存屏障或同步原语
- 编译器/CPU可能对循环进行优化
正确实现需要添加内存屏障或使用atomic操作:
package main
import (
"fmt"
"sync/atomic"
)
var data int32 = 1
var done = make(chan bool)
var last int32 = 1
var in1 int32 = 0
var in2 int32 = 0
func racing1() {
for i := 0; i < 10000; i++ {
atomic.StoreInt32(&last, 1)
atomic.StoreInt32(&in1, 1)
for atomic.LoadInt32(&in2) == 1 && atomic.LoadInt32(&last) == 1 {
// 忙等待
}
atomic.AddInt32(&data, 1)
atomic.StoreInt32(&in1, 0)
}
done <- true
}
func racing2() {
for i := 0; i < 10000; i++ {
atomic.StoreInt32(&last, 2)
atomic.StoreInt32(&in2, 1)
for atomic.LoadInt32(&in1) == 1 && atomic.LoadInt32(&last) == 2 {
// 忙等待
}
atomic.AddInt32(&data, 1)
atomic.StoreInt32(&in2, 0)
}
done <- true
}
func main() {
go racing1()
go racing2()
<-done
<-done
fmt.Println(atomic.LoadInt32(&data))
}
或者使用sync包提供的互斥锁:
package main
import (
"fmt"
"sync"
)
var data int = 1
var done = make(chan bool)
var mu sync.Mutex
func racing1() {
for i := 0; i < 10000; i++ {
mu.Lock()
data = data + 1
mu.Unlock()
}
done <- true
}
func racing2() {
for i := 0; i < 10000; i++ {
mu.Lock()
data = data + 1
mu.Unlock()
}
done <- true
}
func main() {
go racing1()
go racing2()
<-done
<-done
fmt.Println(data)
}
Peterson算法在Go中需要atomic操作来保证内存可见性,否则会出现数据竞争和不正确的结果。


