[Golang]同步工具-sync包的Cond-心智图总结

1. sync包的Cond,提供条件变数。
a. 条件变数是基于互斥锁的,它必须有互斥锁的支撑,才能使用。
b. 条件变数并不是被用来保护共享资源,它是用来协调想要访问共享资源的那些goroutines。
当共享资源的状态发生改变时,它可以被用来通知被互斥锁阻塞的goroutine。
c. 函数:

func NewCond(l Locker) *Condfunc (c *Cond) Broadcast()func (c *Cond) Signal()func (c *Cond) Wait()func (rw *RWMutex) Lock()func (rw *RWMutex) Unlock()func (rw *RWMutex) RLock()func (rw *RWMutex) RUnlock()

2. 条件变数如何和读/写互斥锁一起使用?
参考範例:

package mainimport ("log""sync""time")func main() {// mailbox 代表信箱。// 0代表信箱是空的,1代表信箱是满的。var mailbox uint8// lock 代表信箱上的锁。var lock sync.RWMutex// sendCond 代表专用于发信的条件变数。sendCond := sync.NewCond(&lock)// recvCond 代表专用于收信的条件变数。recvCond := sync.NewCond(lock.RLocker())// sign 用于传递演示完成的信号。sign := make(chan struct{}, 3)max := 5go func(max int) { // 用于发信。defer func() {sign <- struct{}{}}()for i := 1; i <= max; i++ {time.Sleep(time.Millisecond * 500)lock.Lock()for mailbox == 1 {sendCond.Wait()}log.Printf("sender [%d]: the mailbox is empty.", i)mailbox = 1log.Printf("sender [%d]: the letter has been sent.", i)lock.Unlock()recvCond.Signal()}}(max)go func(max int) { // 用于收信。defer func() {sign <- struct{}{}}()for j := 1; j <= max; j++ {time.Sleep(time.Millisecond * 500)lock.RLock()for mailbox == 0 {recvCond.Wait()}log.Printf("receiver [%d]: the mailbox is full.", j)mailbox = 0log.Printf("receiver [%d]: the letter has been received.", j)lock.RUnlock()sendCond.Signal()}}(max)<-sign<-sign}

https://play.golang.org/p/qY4mLfzKSuG

3. 範例细节说明

a. 与sync.Mutex和sync.RWMutex类型不同,sync.Cond类型并不是开箱即用。
需要利用sync.NewCond函数创建它的指标值,而这个函数需要sync.Locker类型的参数值。

b. sendCond和recvCond都是属于*sync.Cond类型,同时使用sync.NewCond函数初始化。

sendCond := sync.NewCond(&lock)recvCond := sync.NewCond(lock.RLocker())

sendCond变数在初始化时,要把lock的指标值传给sync.NewCond函数。
因为,sendCond专门用来对共享资源的写操作。lock变数的Lock和Unlock方法分别用于对写锁的锁定和解锁。

recvCond变数在初始化时,只要把RLocker的值传给sync.NewCond函数。
因为,recvCond只会对共享资源进行读操作。

c. 使用条件变数(sendCond、recvCond),实现单向通知(sendCond.Signal()、recvCond.Signal())。
sender的goroutine开始执行,会阻塞在sendCond.Wait()等待有人发送Signal(sendCond.Signal())。
当sender收到Signal后,就会继续往下执行。
而receiver也是。

http://img2.58codes.com/2024/20131728gfW5BXgqnB.png

参考来源:
郝林-Go语言核心36讲
https://github.com/hyper0x/Golang_Puzzlers
https://golang.org/pkg/cmd/go/internal/test/


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章