如果密钥始终是唯一的,那么同时写入Golang映射是否安全?

时间:2017-07-22 18:49:52

标签: go concurrency channel

package main

import (
    "sync"
    "fmt"
)

var m = make(map[string]string)

var seen = make(map[string]bool)

func main() {
    wg := new(sync.WaitGroup)
    wg.Add(1)
    ch := make(chan string)
    go deduplicate(ch, wg)

    toAdd := []string{"foo", "bar", "baz", "foo"}
    for _, s := range toAdd {
        ch <- s
    }
    wg.Wait()
    fmt.Println(m)
}

func deduplicate(ch chan string, wg *sync.WaitGroup) {
    for s := range ch {
        if seen[s] {
            wg.Done()
            continue
        }
        seen[s] = true
        go write(s)
    }
}

func write(s string) {
    m[s] = "written"   
}

上面的代码是否可以安全使用?请注意,多个字符串将同时写入映射m,但它们肯定是唯一值,因此不会多次写入任何字符串。

2 个答案:

答案 0 :(得分:3)

不,那不安全。密钥是否唯一无关紧要。您需要避免与读取并发的并发写入或写入。并发读取没问题。

您可以使用竞赛检测器通过运行go run -race myprog.go来查找此类问题。请参阅https://golang.org/doc/articles/race_detector.html

答案 1 :(得分:0)

这不安全。 Go地图是自组织数据结构。运行竞赛检测器。

[
{
"Value1": "xxxx",
"Value2": "yyyy",
"Value3": "zzzz"
},
{
"Value1": "qqqq",
"Value2": "eeee",
"Value3": "rrrr"
},
{
"Value1": "1234",
"Value2": "5678",
"Value3": "0987"
},
{
"Value1": "qqqq",
"Value2": "5yy4",
"Value3": "9jf7"
}
]