关于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也会被唤醒(待解决)
有疑问加站长微信联系(非本文作者)