Go map 为什么不是线程安全的?如何解决?
2023-03-25
Go map 不是线程安全的,需要使用 sync 包中的 Mutex 或 RWMutex 来加锁以防止数据竞争和脏数据,确保并发访问时的数据一致性和正确性。
Go map 不是线程安全的原因是因为在多个 goroutine 并发读写 map 时可能会导致数据竞争和不确定的结果,可能读出来的数据是脏数据。因此,在并发情况下需要加锁来保证 map 的线程安全性。
在 Go 中可以使用 sync 包中的 Mutex 或 RWMutex(读写锁)来保证 map 的线程安全性。使用 Mutex 或 RWMutex 可以在读写 map 时加锁,防止多个 goroutine 并发访问,保证数据的一致性和正确性。
下面是使用 Mutex 来实现线程安全的例子:
var m = make(map[string]int)
var mtx sync.Mutex
func main() {
go func() {
for {
// 加锁
mtx.Lock()
m["a"]++
// 解锁
mtx.Unlock()
}
}()
go func() {
for {
mtx.Lock()
m["a"]--
mtx.Unlock()
}
}()
time.Sleep(time.Second)
fmt.Println(m["a"])
}
在上面的例子中,首先创建了一个包含 string
类型键和 int
类型值的 map,然后定义了一个 Mutex 类型的变量 mtx,用于保护 map 的读写。接着创建了两个 goroutine 分别对 map 中的值进行加减操作,每个 goroutine 中加锁操作能够保证在执行修改操作时不会被其它 goroutine 执行中间插入修改操作,避免了数据竞争和脏数据的问题。最后,等待 goroutine 执行完毕并输出 map 中 "a" 键对应的值。