golang 线程安全map
在Go语言中,内置的map
类型本身不是线程安全的。如果多个goroutine同时读写同一个map
,可能会导致数据竞争和未定义行为。为了实现线程安全的map
,可以使用以下几种方法:
sync.Mutex
你可以使用互斥锁(sync.Mutex
)来保护对map
的访问。以下是一个简单的例子:
package main
import (
"fmt"
"sync"
)
type SafeMap struct {
mu sync.Mutex
m map[string]interface{}
}
func NewSafeMap() *SafeMap {
return &SafeMap{
m: make(map[string]interface{}),
}
}
func (sm *SafeMap) Get(key string) (interface{}, bool) {
sm.mu.Lock()
defer sm.mu.Unlock()
val, ok = sm.m[key]
return val, ok
}
func (sm *SafeMap) Set(key string, value interface{}) {
sm.mu.Lock()
defer sm.mu.Unlock()
sm.m[key] = value
}
func (sm *SafeMap) Delete(key string) {
sm.mu.Lock()
defer sm.mu.Unlock()
delete(sm.m, key)
}
func main() {
sm := NewSafeMap()
sm.Set("foo", "bar")
value, ok := sm.Get("foo")
if ok {
fmt.Println("Value:", value)
} else {
fmt.Println("Key not found")
}
}
sync.RWMutex
如果读操作远多于写操作,可以使用读写锁(sync.RWMutex
)来提高性能:
package main
import (
"fmt"
"sync"
)
type SafeMap struct {
mu sync.RWMutex
m map[string]interface{}
}
func NewSafeMap() *SafeMap {
return &SafeMap{
m: make(map[string]interface{}),
}
}
func (sm *SafeMap) Get(key string) (interface{}, bool) {
sm.mu.RLock()
defer sm.mu.RUnlock()
val, ok := sm.m[key]
return val, ok
}
func (sm *SafeMap) Set(key string, value interface{}) {
sm.mu.Lock()
defer sm.mu.Unlock()
sm.m[key] = value
}
func (sm *SafeMap) Delete(key string) {
sm.mu.Lock()
defer sm.mu.Unlock()
delete(sm.m, key)
}
func main() {
sm := NewSafeMap()
sm.Set("foo", "bar")
value, ok := sm.Get("foo")
if ok {
fmt.Println("Value:", value)
} else {
fmt.Println("Key not found")
}
}
sync.Map
Go标准库提供了一个线程安全的map
实现,叫做sync.Map
。它不需要手动加锁,适用于读多写少的场景:
package main
import (
"fmt"
"sync"
)
func main() {
var sm sync.Map
// Store a value
sm.Store("foo", "bar")
// Load a value
value, ok := sm.Load("foo")
if ok {
fmt.Println("Value:", value)
} else {
fmt.Println("Key not found")
}
// Delete a value
sm.Delete("foo")
// Try to load the deleted value
value, ok = sm.Load("foo")
if ok {
fmt.Println("Value:", value)
} else {
fmt.Println("Key not found")
}
}
sync.RWMutex
可能会更高效。sync.Mutex
是一个不错的选择。map
,可以直接使用sync.Map
。根据你的具体需求选择合适的方案来实现线程安全的map
。