【问题标题】:Reliable thread-safe map可靠的线程安全映射
【发布时间】:2020-08-26 14:57:09
【问题描述】:
我正在为我的 Discord 机器人创建一个 WaitForResponse 函数,它可以工作,但即使机器人期待响应,用户仍然可以使用命令。我通过使用带有用户和频道 ID 的地图来解决这个问题,但随后我被可怕的fatal error: concurrent map read and write 击中。所以我尝试使用sync.Map,但是当我发送垃圾邮件命令时它并不总是有效。当机器人期待响应时,我有时仍然可以运行命令。有什么方法可以确保在地图中按应有的方式添加和删除这些值?
【问题讨论】:
标签:
dictionary
go
concurrency
discord
【解决方案1】:
对于这些场景,sync.Mutex 可用于确保只允许进行一次修改,方法是在您希望线程安全的代码周围获取锁。
var mu sync.Mutex
func readMap(key string) {
mu.Lock()
defer mu.Unlock()
return yourMap[key]
}
func updateMap(key, value string) {
mu.Lock()
defer mu.Unlock()
yourMap[key] = value
}
Mutex 确保 ONLY ONE goroutine 可以被允许访问 locked 代码,这意味着对于您的情况,只能执行一个操作,读取或写入。
为了提高效率,您应该考虑使用sync.RWMutex,因为您可能不想在读取地图时锁定它。来自 GoDoc:
RWMutex 是读写器互斥锁。锁可以由任意数量的读取器或单个写入器持有。 RWMutex 的零值是未锁定的互斥锁。
var mu sync.RWMutex
func readMap(key string) {
mu.RLock()
defer mu.RUnlock()
return yourMap[key]
}
func updateMap(key, value string) {
mu.Lock()
defer mu.Unlock()
yourMap[key] = value
}