为了账号安全,请及时绑定邮箱和手机立即绑定

在同一个围棋例程中使用锁和锁

在同一个围棋例程中使用锁和锁

Go
收到一只叮咚 2022-09-26 15:47:54
我正在Go中使用RWMutex进行实验,我意识到通过以下代码可以具有此行为:戈鲁廷 1 - 洛克戈鲁廷 1 - 伦洛克戈鲁廷 2 - 洛克戈鲁廷 2 - 伦洛克戈鲁廷 2 - 锁定戈鲁廷2 - 解锁戈鲁廷 1 - 锁戈鲁廷 1 - 解锁package mainimport (    "fmt"    "sync"    "time")type RLockAndLockStruct struct {    mu sync.RWMutex    mapEx map[string]string}func main() {    r := &RLockAndLockStruct{}    r.mapEx = make(map[string]string)    go r.RLockAndLockTest("test", "goroutine 1 - ")    go r.RLockAndLockTest("test", "goroutine 2 - ")    time.Sleep(4000 * time.Millisecond)}func (r *RLockAndLockStruct) RLockAndLockTest(value string, goroutine string) string {    r.mu.RLock()    fmt.Printf("%sRLock\n", goroutine)    t := r.mapEx[value]    r.mu.RUnlock()    fmt.Printf("%sRUnlock\n", goroutine)    if len(t) <= 0 {        time.Sleep(500 * time.Millisecond)        r.mu.Lock()        fmt.Printf("%sLock\n", goroutine)        r.mapEx[value] = value        r.mu.Unlock()        fmt.Printf("%sUnlock\n", goroutine)        return r.mapEx[value]    }    return t}我在一些文章中读到,在戈鲁廷斯中使用地图的正确方法是使用RWMutex和RLock进行读取和锁定写入。但是,正如您在上面的代码中看到的,如果两个 Goroutine 几乎在同一时间启动,则可能在同一映射中有两个写入,而不是一个写入和一个读取。由此,我在这里有一些问题:有没有办法保证在映射上只写入一个 goroutine(输入上面的 if 代码块)和所有其他使用新值读取该映射的例程(避免输入 if 代码块)?它是戈鲁丁和地图的正确实现吗?
查看完整描述

1 回答

?
烙印99

TA贡献1829条经验 获得超13个赞

这是因为您的代码中有一个争用条件。您读锁定地图以读取它,做出决定,然后写锁定它。不能保证当您获得写锁定时,您做出决定的条件仍然有效。


正确的方法是在锁定后重新测试条件:


    if len(t) <= 0 {

        time.Sleep(500 * time.Millisecond)

        r.mu.Lock()

        if len(r.mapEx[value])<=0 {

          fmt.Printf("%sLock\n", goroutine)

          r.mapEx[value] = value

        }

        r.mu.Unlock()

        return value

请注意上面的用法,否则它将不得不再次访问地图。return value


查看完整回答
反对 回复 2022-09-26
  • 1 回答
  • 0 关注
  • 77 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信