简介 Go标准库提供Cond原语的目的是,为等待 / 通知场景下的并发问题提供支持。Cond通常应用于等待某个条件的一组goroutine,等条件变为true的时候,其中一个goroutine或者所有的goroutine都
简介Go 标准库提供 Cond 原语的目的是,为等待 / 通知场景下的并发问题提供支持。Cond 通常应用于等待某个条件的一组 goroutine,等条件变为 true 的时候,其中一个 goroutine 或者所有的 goroutine 都会被唤醒执行。 Cond 是和某个条件相关,这个条件需要一组 goroutine 协作共同完成,在条件还没有满足的时候,所有等待这个条件的 goroutine 都会被阻塞住,只有这一组 goroutine 通过协作达到了这个条件,等待的 goroutine 才可能继续进行下去。 这个条件可以是我们自定义的 true/false 逻辑表达式。 但是 Cond 使用的比较少,因为在大部分场景下是可以被 Channel 和 WaitGroup 来替换的。 详细介绍下面就是 Cond 的数据结构和对外提供的方法,Cond 内部维护了一个等待队列和锁实例。
案例:Redis连接池可以看一下下面的代码,使用了 Cond 实现一个 Redis 的连接池,最关键的代码就是在链表为空的时候需要调用 Cond 的 Wait 方法,将 gorutine 进行阻塞。然后 goruntine 在使用完连接后,将连接返回池子后,需要通知其他阻塞的 goruntine 来获取连接。
运行结果:
注意点
看一下源码就知道了,因为 Wait 方法的执行逻辑是先将 goruntine 添加到等待队列中,然后释放锁,然后阻塞,等唤醒后,会继续加锁。如果在调用 Wait 前不加锁,但是里面会解锁,执行的时候就会报错。
就拿上面的 redis 连接案例来进行说明吧,我这里是使用了 for 循环来进行检测。如果将 for 循环改成使用 if,也就是只判断一次,会有什么问题?可以停下来先想想 上面说了调用者也可以使用 Broadcast 方法来唤醒 goruntine ,如果使用的是 Broadcast 方法,所有的 goruntine 都会被唤醒,然后大家都去链表中去获取 redis 连接了,就会出现部分 goruntine拿不到连接, 实际上没有那么多连接可以获取,因为每次只会放回一个连接到池子中。
|
2022-04-28
2022-04-21
2022-05-13
2022-08-17
2022-02-25