關於sync.RWMutex
關於優先級
- 爲了模擬pthread中的barrier,在代碼中使用了RWMutex配合阻塞管道.而其中一個關鍵問題就是讀鎖與寫鎖的優先級問題.
- 文檔裏面有這樣一句話:a blocked Lock call excludes new readers from acquiring the lock.
因此咱們能夠看到,一個阻塞的寫鎖會阻止新的讀者請求讀鎖.
- 總結一下,咱們能夠將程序分階段來闡述這個行爲.
- N個讀者添加N個讀鎖
- 一個寫者試圖添加寫鎖被阻塞
- 後續讀者沒法成功獲取讀鎖.
- N個讀鎖所有解鎖
- 寫鎖被喚醒,完成寫操做,解除寫鎖
- 後續讀者被喚醒,得到讀鎖,完成讀操做
- 測試代碼 :
package main
import "fmt"
import "time"
import "sync"
func main() {
var wg sync.WaitGroup
var rw sync.RWMutex
wg.Add(3)
go func() {
defer wg.Done()
rw.RLock()
time.Sleep(3 * time.Second)
rw.RUnlock()
}()
go func() {
defer wg.Done()
time.Sleep(1 * time.Second)
rw.Lock()
fmt.Println("Get Write Lock")
rw.Unlock()
}()
go func() {
defer wg.Done()
time.Sleep(2 * time.Second)
rw.RLock()
fmt.Println("Get Read Lock")
rw.RUnlock()
}()
wg.Wait()
}
輸出: Get Write Lock
Get Read Lock
鎖的喚醒問題
- 當鎖被解除以後會發生什麼.繼續執行goroutine仍是喚醒被等待的鎖?
- 測試代碼:
package main
import "fmt"
import "time"
import "sync"
func main() {
var wg sync.WaitGroup
var fuck sync.RWMutex
wg.Add(2)
go func() {
time.Sleep(20 * time.Millisecond)
for i := 0; i < 1000; i++ {
fuck.Lock()
fmt.Printf("Write lock %d\n",i)
fuck.Unlock()
}
wg.Done()
}()
go func() {
time.Sleep(18 * time.Millisecond)
for i := 0; i < 1000; i++ {
fuck.RLock()
fmt.Printf("Read lock %d\n",i)
fuck.RUnlock()
}
wg.Done()
}()
wg.Wait()
}
輸出:
N * Read lock
Write lock
Read lock
Write lock
Read lock
Write lock
Read lock
....
N * Write lock
- 結論爲解鎖後go會喚醒等待的鎖而不是繼續執行
- 看樣子sleep也會被喚醒(待解決)