go - 具有 CRUD 操作的 RW 锁

标签 go mutex

我不确定我是否正在处理这个问题,这个想法是在读取时具有并发性,但仅在写入、更新或删除时才锁定。

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
}

寻找一种有效的方法,当我从字典中读取时不阻塞,但只在 AddFooRemoveFoo 方法中阻塞。

编辑 上下文略有不同,代码不会由 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/

相关文章:

go - "declared and not used"错误

C - 使用互斥锁同步多个线程

c - pthreads互斥与信号量

operating-system - 测试和设置 vs 彼得森算法

C++(11) "High Performance"并发单个写入器

c++ - 当被调用方法使用调用者已经锁定的相同锁时,如何避免死锁?

go - go 如何计算映射中键的哈希值?

concurrency - 来自 fanIn 示例的 golang 并发模式

go - golang 插件可以用于工厂功能吗?

html - 与 HTML 和 Go 进行前端交互