面试题答案
一键面试在并发编程中使用Go的map时,可能会遇到以下问题:
- 竞态条件:多个goroutine同时读写map会导致未定义行为,如数据损坏或程序崩溃。
解决方法及示例:
使用sync.Map
sync.Map
是Go标准库提供的线程安全的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)
value, ok := m.Load(key)
if ok {
fmt.Printf("goroutine %d read value: %d\n", id, value)
}
}(i)
}
wg.Wait()
}
使用sync.RWMutex
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 < 5; 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)
}
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
key := fmt.Sprintf("key%d", id)
mu.RLock()
value, ok := m[key]
mu.RUnlock()
if ok {
fmt.Printf("goroutine %d read value: %d\n", id, value)
}
}(i)
}
wg.Wait()
}
在这个示例中,写操作使用mu.Lock()
获取独占锁,读操作使用mu.RLock()
获取读锁,从而确保map在并发操作下的安全。