更改地图链接是否并发安全?

big*_*awn -2 concurrency go

您知道吗,在并发环境中将映射变量链接更改为另一个是否安全?

一个例子是datamap 在一个 goroutine 中替换为 new map 并在另一个 goroutine 中从它们中读取元素:

import (
    "fmt"
    "math/rand"
    "strconv"
    "testing"
    "time"
)

func TestMap(t *testing.T) {
    s1 := rand.NewSource(time.Now().UnixNano())
    r1 := rand.New(s1)
    data := fill(r1.Intn(100))

    timer := time.NewTimer(10 * time.Second)

    go func() {
        s1 := rand.NewSource(time.Now().UnixNano())
        r1 := rand.New(s1)

        for {
            select {
            case <-timer.C:
                return
            default:

            }
            p := r1.Intn(100)
            v := fill(p)
            data = v
            fmt.Println("_p=" + strconv.Itoa(p))
        }
    }()

    for range []int{1, 2, 3, 4, 5, 6, 7, 8} {
        go func() {
            s1 := rand.NewSource(time.Now().UnixNano())
            r1 := rand.New(s1)
            for {

                select {
                case <-timer.C:
                    return
                default:

                }

                n := r1.Intn(100)
                s := strconv.Itoa(n)
                fmt.Println(data[s])
            }
        }()
    }

    <-timer.C
}

func fill(postfix int) map[string][]string {
    m := make(map[string][]string)
    for i := 0; i < 100; i++ {
        s := strconv.Itoa(i)
        m[s] = []string{s + "_" + strconv.Itoa(postfix)}
    }
    return m
}
Run Code Online (Sandbox Code Playgroud)

icz*_*cza 5

当然,这并不安全。没有变量(包括映射)对于并发读写是安全的。

你的一个 goroutine 写入data,另一个读取它。运行测试go test -race还会报告数据竞争:

testing.go:954: race detected during execution of test
Run Code Online (Sandbox Code Playgroud)

您必须同步data从多个 goroutine读取和写入变量。