golang sync Cond

Cond在Locker的基础上增加的一个消息通知的功能。但是它只能按照顺序去使一个goroutine解除阻塞。

Cond有三个方法:Wait,Signal,Broadcast。
Wait添加一个计数,也就是添加一个阻塞的goroutine。
Signal解除一个goroutine的阻塞,计数减一。
Broadcast接触所有wait goroutine的阻塞。

那外部传入的Locker,是对wait,Signal,Broadcast进行保护。防止发送信号的时候,不会有新的goroutine进入wait。在wait逻辑完成前,不会有新的事件发生。

注意:在调用Signal,Broadcast之前,应确保目标进入Wait阻塞状态。

例子:

 

package main

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

func main() {
	wait := sync.WaitGroup{}
	locker := new(sync.Mutex)
	cond := sync.NewCond(locker)

	for i := 0; i < 3; i++ {
		go func(i int) {
			defer wait.Done()
			wait.Add(1)
			cond.L.Lock()
			fmt.Println("Waiting start...")
			cond.Wait()
			fmt.Println("Waiting end...")
			cond.L.Unlock()

			fmt.Println("Goroutine run. Number:", i)
		}(i)
	}

	time.Sleep(2e9)
	cond.L.Lock()
	cond.Signal()
	cond.L.Unlock()

	time.Sleep(2e9)
	cond.L.Lock()
	cond.Signal()
	cond.L.Unlock()

	time.Sleep(2e9)
	cond.L.Lock()
	cond.Signal()
	cond.L.Unlock()

	wait.Wait()
}

输出:

Waiting start...
Waiting start...
Waiting start...
Waiting end...
Goroutine run. Number: 0
Waiting end...
Goroutine run. Number: 1
Waiting end...
Goroutine run. Number: 2

可以看出来,每执行一次Signal就会执行一个goroutine。如果想让所有的goroutine执行,那么将所有的Signal换成一个Broadcast方法可以。

发表评论

电子邮件地址不会被公开。

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>