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.

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

报告相同问题?

悬赏问题

  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示
  • ¥15 arduino 步进电机
  • ¥20 程序进入HardFault_Handler
  • ¥15 oracle集群安装出bug
  • ¥15 关于#python#的问题:自动化测试