dounao5856 2019-04-24 16:34
浏览 48
已采纳

带CRUD操作的RW锁

I'm not sure if I'm approaching this right, the idea is to have concurrency while reading but lock only when it's writing or updating or deleting.

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
}

Looking for an efficient approach where I don't block when I'm reading from the dictionary but block only in AddFoo and RemoveFoo methods.

Edit The context is slightly different, the code will not be executed by goroutines but will be used on a server where I've tons of concurrent requests going on.

Edit 2 In case of two maps

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

Adding some more methods.

  • 写回答

1条回答 默认 最新

  • douba7784 2019-04-24 17:05
    关注

    the code will not be executed by goroutines but will be used on a server where I've tons of concurrent requests

    If they're concurrent, they're in goroutines - for example, if you're using the net/http server, every request is in its own goroutine. There are no other concurrency mechanisms, so if you've got concurrency, you're using goroutines, even if your code doesn't explicitly start them.

    You can't "block only in AddFoo and RemoveFoo methods"; that's not how synchronization works. If you share data, you will have to acquire a lock for reads, and you will block on some reads if they happen concurrently to writes. If you don't acquire a lock for reads, you have a race condition.

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

    The alternative would be to share memory by communicating. This is a more complex refactor and there are many ways of doing it depending on your specific needs; it's not something I could offer a solution for based on a "Foo" type generic example.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 求汇川机器人IRCB300控制器和示教器同版本升级固件文件升级包
  • ¥15 用visualstudio2022创建vue项目后无法启动
  • ¥15 x趋于0时tanx-sinx极限可以拆开算吗
  • ¥500 把面具戴到人脸上,请大家贡献智慧
  • ¥15 任意一个散点图自己下载其js脚本文件并做成独立的案例页面,不要作在线的,要离线状态。
  • ¥15 各位 帮我看看如何写代码,打出来的图形要和如下图呈现的一样,急
  • ¥30 c#打开word开启修订并实时显示批注
  • ¥15 如何解决ldsc的这条报错/index error
  • ¥15 VS2022+WDK驱动开发环境
  • ¥30 关于#java#的问题,请各位专家解答!