面试题答案
一键面试在Go语言中,可以使用sync.Map
来确保在并发环境下安全地操作Map。sync.Map
是Go 1.9引入的一个线程安全的map实现。
以下是示例代码展示如何在合并与更新Map键值对时应用sync.Map
:
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
var m sync.Map
// 模拟多个goroutine同时更新Map
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
key := fmt.Sprintf("key%d", id)
value := fmt.Sprintf("value%d", id)
// 插入或更新键值对
m.Store(key, value)
}(i)
}
// 等待所有goroutine完成
wg.Wait()
// 获取并打印所有键值对
m.Range(func(key, value interface{}) bool {
fmt.Printf("Key: %s, Value: %s\n", key, value)
return true
})
}
在上述代码中:
- 我们使用
sync.Map
创建了一个线程安全的mapm
。 - 启动10个goroutine,每个goroutine向
sync.Map
中插入或更新一个键值对。 - 使用
sync.WaitGroup
等待所有goroutine完成操作。 - 使用
m.Range
方法遍历sync.Map
,并打印所有的键值对。
如果不想使用sync.Map
,也可以通过sync.RWMutex
来实现对普通map的并发安全操作:
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
var mu sync.RWMutex
m := make(map[string]string)
// 模拟多个goroutine同时更新Map
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
key := fmt.Sprintf("key%d", id)
value := fmt.Sprintf("value%d", id)
mu.Lock()
// 插入或更新键值对
m[key] = value
mu.Unlock()
}(i)
}
// 等待所有goroutine完成
wg.Wait()
mu.RLock()
// 获取并打印所有键值对
for key, value := range m {
fmt.Printf("Key: %s, Value: %s\n", key, value)
}
mu.RUnlock()
}
在这段代码中:
- 我们使用
sync.RWMutex
来保护普通mapm
。 - 在更新map时,使用
mu.Lock()
加写锁,操作完成后使用mu.Unlock()
解锁。 - 在读取map时,使用
mu.RLock()
加读锁,操作完成后使用mu.RUnlock()
解锁。这样可以保证在并发环境下对map的安全操作。