英文:
Settings and accessing a pointer from concurrent goroutines
问题
在这段伪代码中,存在并发性的问题。具体来说,问题出现在goroutine A和goroutine B同时访问和修改map变量"a"的时候。
在goroutine A中,通过将map赋值给临时变量tempA来使用它。然而,在goroutine B中,通过将新创建的map赋值给变量a来替换原有的map。这样做可能会导致goroutine A在使用tempA期间,map被替换,从而导致数据不一致或错误的结果。
为了解决这个问题,你可以使用互斥锁(mutex)来保护map的访问和修改。在goroutine A中,在访问和使用map之前,获取互斥锁;在goroutine B中,在替换map之前,获取互斥锁。这样可以确保在一个goroutine修改map时,其他goroutine无法同时访问它,从而避免并发冲突。
另外,还可以考虑使用Go语言中提供的并发安全的数据结构,如sync.Map,它已经内置了并发访问的保护机制,可以更方便地处理并发访问map的情况。
英文:
I have a map which is used by goroutine A and replaced once in a time in goroutine B. By replacement I mean:
var a map[T]N
// uses the map
func goroutineA() {
for (...) {
tempA = a
..uses tempA in some way...
}
}
//refreshes the map
func gorountineB() {
for (...) {
time.Sleep(10 * time.Seconds)
otherTempA = make(map[T]N)
...initializes other tempA....
a = otherTempA
}
}
Do you see any problem in this pseudo code? (in terms of concurrecy)
答案1
得分: 7
代码不安全,因为对指针值的赋值和读取不能保证是原子操作。这意味着当一个goroutine写入新的指针值时,另一个goroutine可能会看到旧值和新值的混合字节,这将导致程序以不好的方式崩溃。另一件可能发生的事情是,由于代码中没有同步,编译器可能会注意到没有任何东西可以改变goroutineA中的a,并将tempA := a
语句提升到循环之外。这意味着你将永远看不到其他goroutine更新的新映射赋值。
你可以使用go test -race
自动查找这些问题。
一种解决方案是使用互斥锁锁定对映射的所有访问。
你可以阅读Go内存模型文档,该文档清楚地解释了何时在goroutine内部可见变量的更改。
英文:
The code isn't safe, since assignments and reads to a pointer value are not guaranteed to be atomic. This can mean that as one goroutine writes the new pointer value, the other may see a mix of bytes from the old and new value, which will cause your program to die in a nasty way. Another thing that may happen is that since there's no synchronisation in your code, the compiler may notice that nothing can change a in goroutineA, and lift the tempA := a
statement out of the loop. This will mean that you'll never see new map assignments as the other goroutine updates them.
You can use go test -race
to find these sorts of problems automatically.
One solution is to lock all access to the map with a mutex.
You may wish to read the Go Memory Model document, which explains clearly when changes to variables are visible inside goroutines.
答案2
得分: 3
当对数据竞争不确定时,运行go run -race file.go
,也就是说,是的,会发生竞争。
最简单的解决方法是使用sync.RWMutex:
var a map[T]N
var lk sync.RWMutex
// 使用该map
func goroutineA() {
for (...) {
lk.RLock()
// 对a进行操作
lk.RUnlock()
}
}
// 刷新该map
func goroutineB() {
for (...) {
otherTempA = make(map[T]N)
//...初始化其他的tempA....
lk.Lock()
a = otherTempA
lk.Unlock()
}
}
英文:
When unsure about data races, run go run -race file.go
, that being said, yes there will be a race.
The easiest way to fix that is using a sync.RWMutex :
var a map[T]N
var lk sync.RWMutex
// uses the map
func goroutineA() {
for (...) {
lk.RLock()
//actions on a
lk.RUnlock()
}
}
//refreshes the map
func gorountineB() {
for (...) {
otherTempA = make(map[T]N)
//...initializes other tempA....
lk.Lock()
a = otherTempA
lk.Unlock()
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论