go 条件变量

条件等待和互斥锁有不同,互斥锁是不同协程公用一个锁,条件等待是不同协程各用一个锁,但
是wait()方法调用会等待(阻塞),直到有信号发过来,不同协程是共用信号。

Wait() 阻塞当前协成

func (c *Cond) Wait() {
    c.checker.check()
    t := runtime_notifyListAdd(&c.notify)  // 等待的goruntine数+1
    c.L.Unlock() // 释放锁资源
    runtime_notifyListWait(&c.notify, t) // 阻塞,等待其他goruntine唤醒
    c.L.Lock() // 获取资源
}

Signa() 和 BroadCast()  唤醒协成

func (c *Cond) Signal() {
    c.checker.check()
    runtime_notifyListNotifyOne(&c.notify) // 唤醒最早被阻塞的goruntine
}

func (c *Cond) Broadcast() {
    c.checker.check()
    runtime_notifyListNotifyAll(&c.notify) // 唤醒所有goruntine
}

 demo

package main
import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

var cond sync.Cond

//生产者
func producer(out chan<- int, index int){
	for{
		cond.L.Lock()
		for len(out) == 10 {
			fmt.Println(index, "len == 10")
			cond.Wait()//阻塞 等待
		}
		num := rand.Intn(800)
		time.Sleep(time.Second)
		out<- num
		fmt.Println("生产者:",index, num)

		cond.L.Unlock()
		cond.Signal()//唤醒阻塞的协程
	}
}

//消费者
func consumer(in <-chan int, index int){
	for{
		cond.L.Lock()
		for len(in) == 0 {
			fmt.Println(index, "len == 0")
			cond.Wait()//阻塞 等待
		}
		time.Sleep(time.Second)
		num := <-in
		fmt.Println("消费者:",index,num)
		cond.L.Unlock()
		cond.Signal()//唤醒阻塞的协程
	}

}
func main() {
	ch := make(chan int, 10)
	rand.Seed(time.Now().UnixMilli())
	cond.L = new(sync.Mutex)

	for i:=1; i<=4; i++{
		go producer(ch, i)
	}

	for i:=1; i<=6; i++{
		go consumer(ch, i)
	}

	quit := make(chan []struct{})
	<-quit

}

demo2

package main

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


	var (
		done = false
		topic = "Golang梦工厂"
	)

	func main() {
		cond := sync.NewCond(&sync.Mutex{})
		go Consumer(topic,cond)
		go Consumer(topic,cond)
		go Consumer(topic,cond)
		Push(topic,cond)
		time.Sleep(5 * time.Second)

	}

	func Consumer(topic string,cond *sync.Cond)  {
		cond.L.Lock()
		for !done{
			cond.Wait()
		}
		fmt.Println("topic is ",topic," starts Consumer")
		cond.L.Unlock()
	}

	func Push(topic string,cond *sync.Cond)  {
		fmt.Println(topic,"starts Push")
		cond.L.Lock()
		done = true
		cond.L.Unlock()
		fmt.Println("topic is ",topic," wakes all")
		cond.Broadcast()
	}
	// 运行结果
	//Golang梦工厂 starts Push
	//topic is  Golang梦工厂  wakes all
	//topic is  Golang梦工厂  starts Consumer
	//topic is  Golang梦工厂  starts Consumer
	//topic is  Golang梦工厂  starts Consumer

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值