忽视在Go语言中使用映射时的goroutine/线程安全性会带来什么危险?

huangapple go评论83阅读模式
英文:

What is the danger of neglecting goroutine/thread-safety when using a map in Go?

问题

Go的map据说不是goroutine-safe(参见这里这里)。我对于在我忽略使用互斥锁等保护对map的访问时可能发生的情况很感兴趣。

具体来说,以下情况是否可能发生?

  1. 假设我有一个带有键k1k2,...,kn的map,是否可能由于并发问题导致在请求map[kj]时获取到map[ki](i != j)?
  2. 是否可能导致应用程序发生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?

  1. Assuming I have a map with keys k1, k2, ..., kn, can a concurrency issue lead to getting map[ki] when I asked for map[kj] (i != j)?
  2. 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()

huangapple
  • 本文由 发表于 2016年2月16日 19:17:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/35431102.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定