我正在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
- 1 回答
- 0 关注
- 77 浏览
添加回答
举报
0/150
提交
取消