工作生活

go中的fatal error:concurrent map r

2019-07-01  本文已影响0人  天地一小儒

在Go中,如果不对map做同步控制,高并发读写时,会出现fatal级别的错误。复现例子:

错误示例


package rabbit

import (
    "fmt"
    "testing"
    "time"
)

var count = 100000

func Test_NonConcurrentMap(t *testing.T) {
    nonCMap := make(map[int]struct{})
    go WriteNonCMap(nonCMap)
    go ReadNonCMap(nonCMap)

    // To see the fatal
    time.Sleep(10 * time.Second)
}

func WriteNonCMap(nonCMap map[int]struct{}) {
    for index := 0; index < count; index++ {
        nonCMap[index] = struct{}{}
    }
}

func ReadNonCMap(nonCMap map[int]struct{}) {
    for index := 0; index < count; index++ {
        fmt.Print(nonCMap[index])

    }
}

错误结果


测试Test_NonConcurrentMap 函数会报错:fatal error: concurrent map read and map write

image.png

如果恰好没有报错,则可以提升主进程的sleep时间,增大碰撞区间,或增加count的数量,延长碰撞时间。

错误原因

因为这两个程序都是对一个map去访问,当两个协程同时的去访问这个map时,就会发生资源竞争,进而报错。

解决方法

  1. sync.map
package rabbit

import (
    "fmt"
    "sync"
    "testing"
    "time"
)

var count = 100000

func Test_ConcurrentMap(t *testing.T) {
    cMap := &sync.Map{}
    go WriteCMap(cMap)
    go ReadCMap(cMap)

    // Never fatal
    time.Sleep(10 * time.Second)
}

func WriteCMap(cMap *sync.Map) {
    for index := 0; index < count; index++ {
        cMap.Store(index, struct{}{})
    }
}

func ReadCMap(cMap *sync.Map) {
    for index := 0; index < count; index++ {
        fmt.Print(cMap.Load(index))
    }
}
  1. channel
上一篇下一篇

猜你喜欢

热点阅读