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也会被唤醒(待解决)
相关文章
相关标签/搜索