【面试指南】golang-map注意事项

map 非并发安全的

众所周知,go 基础类型中的 map 是非并发安全的,多个 goroutine 同时对同一个 map 进行读写操作时,可能会导致并发写问题,

package main

import (
    "fmt"
)

func main() {
    
    m := make(map[string]string)
    go func() {
       m["a"] = "a"
    }()
    m["a"] = "a1"
    fmt.Println(m["a"])
}

我们可以使用 go run -race ./cmd/test/main.go 命令来检查是否有并发安全问题:

==================
WARNING: DATA RACE
Write at 0x00c0000920c0 by goroutine 6:
  runtime.mapaccess2_faststr()
      /usr/local/go/src/runtime/map_faststr.go:108 +0x42c
  main.main.func1()
      ./main.go:11 +0x40

==================
WARNING: DATA RACE
Previous write at 0x00c0000ae088 by main goroutine:
  main.main()
      ./main.go:13 +0xb0
==================
Found 2 data race(s)
exit status 66

诸如上述报错,我们可以发现第 11 行m["a"] = "a"跟 13 行m["a"] = "a1"存在DATA RACE数据竞争。
那么,我们会想到可以加锁避免数据竞争问题,如下代码:

package test

import (
    "sync"
    "testing"
)

// 无锁调用
func BenchmarkAddMapUnLock(b *testing.B) {
    for i := 0; i < b.N; i++ {
       addMapUnLock()
    }
}
func addMapUnLock() {
    m := make(map[int]int)
    for i := 1; i <= 100000; i++ {
       m[i] = i
    }
}

// 有锁调用
func BenchmarkAddMapLock(b *testing.B) {
    for i := 0; i < b.N; i++ {
       addMapLock()
    }
}
func addMapLock() {
    var mu sync.Mutex
    m := make(map[int]int)
    for i := 1; i <= 100000; i++ {
       mu.Lock()
       m[i] = i
       mu.Unlock()
    }
}

你可能感兴趣的:(面试,golang,职场和发展)