Golang映射用于并发读/写操作的安全性如何? [英] How safe are Golang maps for concurrent Read/Write operations?

查看:309
本文介绍了Golang映射用于并发读/写操作的安全性如何?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据Go博客,


地图不能安全用于并发使用:未定义读取和写入时会发生什么他们同时。如果需要从并发执行的goroutine读取和写入映射,访问必须通过某种同步机制来调解。
(来源:


According to the Go blog,

Maps are not safe for concurrent use: it's not defined what happens when you read and write to them simultaneously. If you need to read from and write to a map from concurrently executing goroutines, the accesses must be mediated by some kind of synchronization mechanism. (source: https://blog.golang.org/go-maps-in-action)

Can anyone elaborate on this? Concurrent read operations seem permissible across routines, but concurrent read/write operations may generate a race condition if one attempts to read from and write to the same key.

Can this last risk be reduced in some cases? For example:

  • Function A generates k and sets m[k]=0. This is the only time A writes to map m. k is known to not be in m.
  • A passes k to function B running concurrently
  • A then reads m[k]. If m[k]==0, it waits, continuing only when m[k]!=0
  • B looks for k in the map. If it finds it, B sets m[k] to some positive integer. If it doesn't it waits until k is in m.

This isn't code (obviously) but I think it shows the outlines of a case where even if A and B both try to access m there won't be a race condition, or if there is it won't matter because of the additional constraints.

解决方案

Before Golang 1.6, concurrent read is ok, concurrent write is not ok, but write and concurrent read is ok. Since Golang 1.6, map cannot be read when it's been writing. So After Golang 1.6, concurrent access map should be like:

package main

import (
        "sync"
        "time"
)

var m = map[string]int{"a": 1}
var lock = sync.RWMutex{}

func main() {
        go Read()
        time.Sleep(1 * time.Second)
        go Write()
        time.Sleep(1 * time.Minute)
}

func Read() {
        for {
                lock.RLock()
                defer lock.RUnlock()
                _ = m["a"]
        }
}

func Write() {
        for {
                lock.Lock()
                defer lock.Unlock()
                m["b"] = 2
        }
}

Or you will get the error below:

这篇关于Golang映射用于并发读/写操作的安全性如何?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆