Go学习笔记 -- sync.Cond条件变量

简介

  sync.Cond 是基于互斥锁/读写锁实现的条件变量,用来协调想要访问共享资源的那些 Goroutine。当共享资源状态发生变化时,sync.Cond 可以用来通知等待条件发生而阻塞的 Goroutine

与互斥锁的关系

  首先,条件变量是基于互斥锁/读写锁实现的,条件变量的初始化离不开互斥锁。
  其次,互斥锁的目的是为了保护临界区和共享资源,而条件变量是为了协调想要访问这些共享资源的协程。

使用场景

我可以使用条件变量来实现生产者消费者场景等。
如下:

import (
	"fmt"
	"sync"
	"time"
)

var stage = 0
var lock sync.Mutex
var pCond = sync.NewCond(&lock) //等待生产的条件变量
var cCond = sync.NewCond(&lock) //等待消费的条件变量

func produce() {
    
    
	pCond.L.Lock() //先获取条件变量中的锁
	defer pCond.L.Unlock()//使用defer函数在方法执行完之后解锁
	for stage == 1 {
    
     //使用 for 判断当前条件是否需要等待,避免假唤醒,当有商品时,不生产。
		pCond.Wait()//等待商品被消费后的通知
	}
	//正常生产商品
	stage = 1
	fmt.Println("生产成功")
	//通知消费者消费
	cCond.Signal()//唤醒最靠前的一个协程
}

func consume() {
    
    
	cCond.L.Lock()
	for stage == 0 {
    
    
		cCond.Wait()
	}
	//正常消费商品
	stage = 0
	fmt.Println("消费成功")
	cCond.L.Unlock()
	//通知生产者生产
	pCond.Signal() 
}

func main() {
    
    
	count := 5
	for i := 0; i < count; i++ {
    
    
		go consume()
		go produce()
	}
	time.Sleep(time.Millisecond * 1000)
}
----------------------------------
生产成功
消费成功
生产成功
消费成功
生产成功
消费成功
生产成功
消费成功
生产成功
消费成功

Signal 和 Boardcast 的区别

首先,cond.Wait() 会将当前协程添加到通知队伍的队尾,当使用 Signal 唤醒等待的协程时,只能唤醒队伍首部的协程。
而使用 Boardcast 会唤醒所有等待的协程。

注意事项

  1. Wait方法需要在它基于的互斥锁保护下执行,否则就会引发不可恢复的 panic,所以我们在调用该方法之前需要先获取其基于的互斥锁。
  2. SignalBoardcast 方法不需要受到互斥锁的保护,而且最好不要在解锁互斥锁之前调用这两个方法。

猜你喜欢

转载自blog.csdn.net/qq_40096897/article/details/128441774