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也会被唤醒(待解决)
posted @ 2017-06-04 10:57  XLLL  阅读(370)  评论(0编辑  收藏  举报