Go 语言中使用 sync.Cond 条件变量来同步并发执行的协程

本文通过详细解释Go语言代码,展示了如何使用sync.Cond条件变量来同步10个并发执行的协程,确保所有运动员准备就绪后比赛开始。
摘要由CSDN通过智能技术生成
  • 经典代码示例
package main

import (
	"log"
	"math/rand"
	"sync"
	"time"
)

func main() {

	c := sync.NewCond(&sync.Mutex{})
	var ready int

	for i := 0; i < 10; i++ {
		go func(i int) {
			time.Sleep(time.Duration(rand.Int63n(10)) * time.Second)

			// 加锁更改等待条件
			c.L.Lock()
			ready++
			c.L.Unlock()

			log.Printf("运动员#%d 已准备就绪\n", i)
			// 广播唤醒所有的等待者
			c.Broadcast()
		}(i)
	}

	c.L.Lock()
	for ready != 10 {
		c.Wait()
		log.Println("裁判员被唤醒一次")
	}
	c.L.Unlock()

	//所有的运动员是否就绪
	log.Println("所有运动员都准备就绪。比赛开始,3,2,1, ......")
}

这段代码演示了如何使用 Go 语言中的 sync.Cond 条件变量来同步并发执行的协程。下面是代码的详细解释:

  1. 首先,我们创建了一个条件变量 c,它用来监控一定的条件(在本例中是运动员是否准备好)。条件变量与互斥锁(sync.Mutex{})相关联,因为条件往往涉及共享资源的状态(此处为 ready 变量)。
c := sync.NewCond(&sync.Mutex{})
var ready int
  1. 我们开启 10 个协程,每个代表一个运动员。每个协程将随机等待一段时间,模拟运动员准备就绪所需的时间。
for i := 0; i < 10; i++ {
	go func(i int) {
		time.Sleep(time.Duration(rand.Int63n(10)) * time.Second)
  1. 当运动员准备好后,协程会锁定与条件变量关联的互斥锁,增加 ready 计数,并通过调用 c.Broadcast() 唤醒所有等待该条件的协程(此例中,裁判员正在等待所有运动员准备好)。
// 加锁更改等待条件
c.L.Lock()
ready++
c.L.Unlock()

log.Printf("运动员#%d 已准备就绪\n", i)
// 广播唤醒所有的等待者
c.Broadcast()
  1. 主协程(裁判员)在开始比赛之前需要确保所有的运动员都已准备就绪。为此,它锁定互斥锁并检查 ready 计数是否等于 10(即所有运动员都已准备好)。如果没有,则调用 c.Wait() 进入等待状态。当 c.Broadcast() 被某个运动员调用时,裁判员被唤醒,再次检查条件是否满足。
c.L.Lock()
for ready != 10 {
	c.Wait()
	log.Println("裁判员被唤醒一次")
}
c.L.Unlock()

在调用 c.Wait() 时,互斥锁会被自动释放,以便其他协程可以锁定它来改变条件。当 c.Wait() 返回时,互斥锁会被重新锁定,以便协程可以安全地检查条件。

  1. 最后,当所有的运动员都准备就绪时(即 ready 等于 10),主协程(裁判员)会解锁互斥锁并声明所有运动员都准备好了,比赛可以开始。
log.Println("所有运动员都准备就绪。比赛开始,3,2,1, ......")

总之,这段代码通过条件变量 sync.Cond 来同步多个协程间的状态,在本例中是等待所有运动员准备就绪。这是一种常用的同步模式,特别适合于多个协程需要等待某个条件达成才能继续执行的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值