带有CRUD操作的RW锁

时间:2019-04-24 16:34:27

标签: 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 (如果有两个地图)

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]
}

添加更多方法。

1 个答案:

答案 0 :(得分:1)

  

该代码不会由goroutine执行,而是将在我有大量并发请求的服务器上使用

如果它们是并发的,则它们在goroutine中-例如,如果您使用net/http服务器,则每个请求都在其自己的goroutine中。没有其他并发机制,因此,即使有并发机制,也可以使用goroutine,即使您的代码没有明确启动它们。

您不能“仅在AddFoo和RemoveFoo方法中阻止”;同步不是这样的。如果共享数据,则必须获得读取锁,并且如果某些读取与写入同时发生,则将阻止某些读取。如果您未获得读取锁,则说明您存在竞争状况。

func (d *Data) GetFoo(name string) Foo {
    d.RLock()
    d.RUnlock()
    return d.fooMap[name]
}

另一种选择是通过通信共享内存。这是一个更复杂的重构,并且有多种方法可以实现,具体取决于您的特定需求。我无法提供基于“ Foo”类型的通用示例的解决方案。