我不确定我是否正在处理这个问题,这个想法是在读取时具有并发性,但仅在写入、更新或删除时才锁定。
type Data struct {
sync.RWMutex
fooMap map[string]Foo
}
func (d *Data) AddFoo(foo Foo) {
d.Lock()
defer d.Unlock()
d.fooMap[foo.getName()] = foo
}
func (d *Data) GetFoo(name string) Foo {
return d.fooMap[name]
}
func (d *Data) RemoveFoo(name string) Foo {
d.Lock()
defer d.Unlock()
var foo = self.fooMap[name]
if foo != nil {
delete(d.fooMap, name)
}
return foo
}
func (d *Data) HasFoo(name string) bool {
return d.fooMap[name] != nil
}
寻找一种有效的方法,当我从字典中读取时不阻塞,但只在 AddFoo
和 RemoveFoo
方法中阻塞。
编辑
上下文略有不同,代码不会由 goroutines
执行,但会在我有大量并发请求的服务器上使用。
编辑2如果有两张 map
type Data struct {
sync.RWMutex
BarMutex sync.RWMutex{}
fooMap map[string]Foo
barMap map[string]Bar
}
// for Foo
func (d *Data) AddFoo(foo Foo) {
d.Lock()
defer d.Unlock()
d.fooMap[foo.getName()] = foo
}
func (d *Data) GetFoo(name string) Foo {
return d.fooMap[name]
}
// for Bar
func (d *Data) AddBar(bar Bar) {
d.BarMutex.Lock()
defer d.BarMutex.Unlock()
d.barMap[bar.getName()] = bar
}
func (d *Data) GetBar(name string) Bar {
d.BarMutex.RLock()
defer d.BarMutex.RUnlock();
return d.barMap[name]
}
添加更多方法。
最佳答案
the code will not be executed by goroutines but will be used on a server where I've tons of concurrent requests
如果它们是并发的,则它们在 goroutine 中 - 例如,如果您使用 net/http
服务器,则每个请求都在其自己的 goroutine 中。没有其他并发机制,所以如果你有并发,你就是在使用 goroutines,即使你的代码没有明确启动它们。
你不能“只在 AddFoo 和 RemoveFoo 方法中阻塞”;那不是同步的工作方式。如果共享数据,则必须为读取获取锁,并且如果它们同时发生在写入上,您将阻塞某些读取。如果您没有为读取获取锁,就会出现竞争条件。
func (d *Data) GetFoo(name string) Foo {
d.RLock()
d.RUnlock()
return d.fooMap[name]
}
另一种方法是通过通信共享内存。这是一个更复杂的重构,根据您的具体需要,有很多方法可以实现;我无法基于“Foo”类型的通用示例提供解决方案。
关于go - 具有 CRUD 操作的 RW 锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55834776/