我正在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 關注
- 111 瀏覽
添加回答
舉報
0/150
提交
取消