首页 > 解决方案 > 等待互斥体而不获取它

问题描述

我一直在编写一个小型微服务,以便熟悉 Go 及其并发机制。

在我的程序中,我有一个具有状态的结构,我想同步该状态,以便多个 goroutine 能够读取它,但不能在另一个 goroutine 更新该状态时读取它。

最初我认为 RWMutax 是我需要的,但是根据文档,只有一个 goroutine 可以在任何给定的时刻获取读取锁。我走这条线:

“如果一个 goroutine 持有一个用于读取的 RWMutex,而另一个 goroutine 可能会调用 Lock,那么在释放初始读取锁之前,任何 goroutine 都不应该期望能够获取读取锁。”

有没有办法在不获取锁的情况下等待互斥锁?

类似于:

type stateful struct {
    state        int
    stateMutex   sync.Mutex
    beingUpdated bool
}

type Stateful interface {
    GetState() int
    SetState(st int)
}

func createStateful (sa string) stateful {
    return server{state: 0, stateMutex: sync.Mutex{}, beingUpdated: false}
}

func (s *stateful) SetState(st int) {
    s.stateMutex.Lock()
    s.beingUpdated = true
    s.state = st
    s.beingUpdated = false
    s.stateMutex.Unlock()
}

func (s *stateful) GetState() bool {
    if s.beingUpdated {
        // wait for s.stateMutex to be unlocked
    }

    return s.state
}

标签: goconcurrencymutex

解决方案


您可能误读了sync.RWMutex 文档

...锁可以由任意数量的读者或单个作者持有。

所以你的代码简化如下:

type stateful struct {
    l     sync.RWMutex // style: place lock above ...
    state int        //        ... the field it protects
}

func (s *stateful) SetState(st int) {
    s.l.Lock()
    defer s.l.Unlock()

    s.state = st
}

func (s *stateful) GetState() int {
    s.l.RLock()
    defer s.l.RUnlock()

    return s.state
}

推荐阅读