英文:
What is the danger of neglecting goroutine/thread-safety when using a map in Go?
问题
Go的map
据说不是goroutine-safe
(参见这里和这里)。我对于在我忽略使用互斥锁等保护对map的访问时可能发生的情况很感兴趣。
具体来说,以下情况是否可能发生?
- 假设我有一个带有键
k1
,k2
,...,kn
的map,是否可能由于并发问题导致在请求map[kj]
时获取到map[ki]
(i != j)? - 是否可能导致应用程序发生
panic
?
英文:
Go's map
is said not to be goroutine-safe
(see here and here). I'm interested at finding out what could happen in a case where I neglect to protect access to the map using mutex/etc.
Specifically, can any of the following happen?
- Assuming I have a map with keys
k1
,k2
, ...,kn
, can a concurrency issue lead to gettingmap[ki]
when I asked formap[kj]
(i != j)? - Can it lead to a
panic
in the application?
答案1
得分: 8
正如评论中已经提到的,竞态条件是不好的。与Java不同,Go语言的保证非常弱,因此即使在未执行包含竞态条件的代码时,程序仍然可以具有未定义的行为。在C语言中,这被称为“catch-fire语义”。竞态条件的存在意味着任何结果都是可能的,包括你的计算机着火。
然而,在Go语言中,很容易使一个map线程安全。考虑以下代码:
// 定义一个全局变量map
var safemap = struct {
sync.RWMutex
m map[string]string
}{m: make(map[string]string)}
你可以像这样安全地从map中读取数据:
// 获取读锁,然后从map中读取数据
safemap.RLock()
defer safemap.RUnlock()
return safemap.m[mykey] == myval
你也可以像这样安全地进行修改:
// 从map中删除数据
safemap.Lock()
delete(safemap.m, mykey)
safemap.Unlock()
或者像这样插入数据:
// 向map中插入数据
safemap.Lock()
safemap.m[mykey] = myval
safemap.Unlock()
英文:
As the comments have already stated, races are bad. Go has very weak guarantees, unlike Java, and hence a program that has any race is allowed to have undefined behavior even when the race-containing code is not executed. In C, this is called "catch-fire semantics". The presence of a race means any outcome is possible, to include your computer catching on fire.
However, in Go it is easy to make a map thread-safe. Consider the following:
// Global variable defining a map
var safemap = struct {
sync.RWMutex
m map[string]string
}{m: make(map[string]string)}
You can do safe reads from the map like this:
// Get a read lock, then read from the map
safemap.RLock()
defer safemap.RUnlock()
return safemap.m[mykey] == myval
And you can do safe modifications like this:
// Delete from the map
safemap.Lock()
delete(safemap.m, mykey)
safemap.Unlock()
or this:
// Insert into the map
safemap.Lock()
safemap.m[mykey] = myval
safemap.Unlock()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论