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

我正在Go中使用RWMutex进行实验,我意识到通过以下代码可以具有此行为:

  • 戈鲁廷 1 - 洛克

  • 戈鲁廷 1 - 伦洛克

  • 戈鲁廷 2 - 洛克

  • 戈鲁廷 2 - 伦洛克

  • 戈鲁廷 2 - 锁定

  • 戈鲁廷2 - 解锁

  • 戈鲁廷 1 - 锁

  • 戈鲁廷 1 - 解锁

package main


import (

    "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 几乎在同一时间启动,则可能在同一映射中有两个写入,而不是一个写入和一个读取。

由此,我在这里有一些问题:

  1. 有没有办法保证在映射上只写入一个 goroutine(输入上面的 if 代码块)和所有其他使用新值读取该映射的例程(避免输入 if 代码块)?

  2. 它是戈鲁丁和地图的正确实现吗?


收到一只叮咚
浏览 82回答 1
1回答

烙印99

这是因为您的代码中有一个争用条件。您读锁定地图以读取它,做出决定,然后写锁定它。不能保证当您获得写锁定时,您做出决定的条件仍然有效。正确的方法是在锁定后重新测试条件:&nbsp; &nbsp; if len(t) <= 0 {&nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(500 * time.Millisecond)&nbsp; &nbsp; &nbsp; &nbsp; r.mu.Lock()&nbsp; &nbsp; &nbsp; &nbsp; if len(r.mapEx[value])<=0 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("%sLock\n", goroutine)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r.mapEx[value] = value&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; r.mu.Unlock()&nbsp; &nbsp; &nbsp; &nbsp; return value请注意上面的用法,否则它将不得不再次访问地图。return value
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go