go中的fatal error:concurrent map read and map write

2022-12-28 14:00:24 浏览数 (2)

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

错误示例


代码语言:javascript复制
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
代码语言:javascript复制
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

0 人点赞