Golang中的RWMutex相關

關於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也會被喚醒(待解決)
相關文章
相關標籤/搜索