MST

星途 面试题库

面试题:Go语言中Map并发读写会出现什么问题及常见解决思路

在Go语言中,对Map进行并发读写操作会引发什么错误?请简要描述常见的解决方案有哪些。
47.1万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

在Go语言中,对Map进行并发读写操作会引发fatal error: concurrent map read and map write错误。这是因为Go语言的Map不是线程安全的,多个goroutine同时读写会导致数据竞争和未定义行为。

常见的解决方案有:

  1. 使用sync.Mutex
package main

import (
    "fmt"
    "sync"
)

func main() {
    var mu sync.Mutex
    m := make(map[string]int)
    var wg sync.WaitGroup

    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            key := fmt.Sprintf("key%d", id)
            mu.Lock()
            m[key] = id
            mu.Unlock()
        }(i)
    }

    wg.Wait()
    mu.Lock()
    fmt.Println(m)
    mu.Unlock()
}

通过sync.Mutex来保护对Map的读写操作,在读写前加锁,读写完成后解锁。

  1. 使用sync.RWMutex
package main

import (
    "fmt"
    "sync"
)

func main() {
    var mu sync.RWMutex
    m := make(map[string]int)
    var wg sync.WaitGroup

    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            key := fmt.Sprintf("key%d", id)
            mu.Lock()
            m[key] = id
            mu.Unlock()
        }(i)
    }

    wg.Wait()
    mu.RLock()
    fmt.Println(m)
    mu.RUnlock()
}

sync.RWMutex允许多个读操作并发执行,但写操作必须独占。读操作使用RLockRUnlock,写操作使用LockUnlock

  1. 使用sync.Map
package main

import (
    "fmt"
    "sync"
)

func main() {
    var m sync.Map
    var wg sync.WaitGroup

    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            key := fmt.Sprintf("key%d", id)
            m.Store(key, id)
        }(i)
    }

    wg.Wait()
    m.Range(func(key, value interface{}) bool {
        fmt.Printf("key: %v, value: %v\n", key, value)
        return true
    })
}

sync.Map是Go 1.9引入的线程安全的Map实现,它提供了StoreLoadLoadOrStoreDeleteRange等方法来进行并发安全的操作。