Golang Map并发安全

在Golang中,当多个goroutine同时读写同一个map时会出现并发安全问题吗?如果需要保证map的并发安全,有哪些常用的解决方案?sync.Map和加锁(map+Mutex)哪种方式性能更好,各自适合什么场景?在处理高并发读写时有哪些最佳实践需要注意?

2 回复

Golang的map在并发读写时非线程安全,可能导致panic。建议使用sync.Map或结合sync.RWMutex实现并发安全。在高并发读少写多场景下,sync.Map性能更优。

更多关于Golang Map并发安全的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go语言中,标准的map类型不是并发安全的。当多个goroutine同时对同一个map进行读写操作时,可能导致数据竞争(data race)和运行时panic。


解决方案

1. 使用互斥锁(sync.Mutex / sync.RWMutex)

通过互斥锁保护map的并发访问:

package main

import (
	"sync"
)

type SafeMap struct {
	mu sync.RWMutex
	m  map[string]int
}

func NewSafeMap() *SafeMap {
	return &SafeMap{
		m: make(map[string]int),
	}
}

func (s *SafeMap) Set(key string, value int) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.m[key] = value
}

func (s *SafeMap) Get(key string) (int, bool) {
	s.mu.RLock()
	defer s.mu.RUnlock()
	val, ok := s.m[key]
	return val, ok
}

func (s *SafeMap) Delete(key string) {
	s.mu.Lock()
	defer s.mu.Unlock()
	delete(s.m, key)
}

2. 使用sync.Map

Go 1.9+ 提供了并发安全的sync.Map,适用于读多写少的场景:

package main

import (
	"sync"
)

func main() {
	var sm sync.Map

	// 存储键值对
	sm.Store("key1", 100)
	sm.Store("key2", 200)

	// 读取
	if val, ok := sm.Load("key1"); ok {
		println(val.(int)) // 输出: 100
	}

	// 删除
	sm.Delete("key2")

	// 遍历所有键值
	sm.Range(func(key, value interface{}) bool {
		println(key.(string), value.(int))
		return true // 继续遍历
	})
}

选择建议

  • 互斥锁方案:适用于需要复杂操作或一致性要求高的场景。
  • sync.Map:适用于读多写少、不需要复杂事务的场景,性能更好。

注意:并发编程时务必通过go run -race进行数据竞争检测。

回到顶部