Golang sync.Cond详细理解

sync.Cond用于goroutine之间的协作,用于协程的挂起和唤醒。

结构体

type Cond struct {
	noCopy noCopy  // noCopy可以嵌入到结构中,在第一次使用后不可复制,使用go vet作为检测使用

	L Locker // 根据需求初始化不同的锁,如*Mutex 和 *RWMutex

	notify  notifyList  // 通知列表,调用Wait()方法的goroutine会被放入list中,每次唤醒,从这里取出
	checker copyChecker // 复制检查,检查cond实例是否被复制
}

 

相关函数

Wait函数

func (c *Cond) Wait() {
        // 检查c是否是被复制的,如果是就panic
	c.checker.check()
	// 将当前goroutine加入等待队列
	t := runtime_notifyListAdd(&c.notify)
	// 解锁
	c.L.Unlock()
	// 等待队列中的所有的goroutine执行等待唤醒操作
	runtime_notifyListWait(&c.notify, t)
	c.L.Lock()
}

功能: 必须获取该锁之后才能调用Wait()方法,Wait方法在调用时会释放底层锁Locker,并且将当前goroutine挂起,直到另一个goroutine执行Signal或者Broadcase,该goroutine才有机会重新唤醒,并尝试获取Locker,完成后续逻辑。

也就是在等待被唤醒的过程中是不占用锁Locker的,这样就可以有多个goroutine可以同时处于Wait(等待被唤醒的状态)

 

Signal函数

func (c *Cond) Signal() {
       // 检查c是否是被复制的,如果是就panic
	c.checker.check()
	// 通知等待列表中的一个 
	runtime_notifyListNotifyOne(&c.notify)
}

功能:唤醒等待队列中的一个goroutine,一般都是任意唤醒队列中的一个goroutine

 

Broadcast函数

func (c *Cond) Broadcast() {
    // 检查c是否是被复制的,如果是就panic
	c.checker.check()
	// 唤醒等待队列中所有的goroutine
	runtime_notifyListNotifyAll(&c.notify)
}

功能:唤醒等待队列中的所有goroutine

 

示例

package main

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

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

	for i := 0 ; i < 30 ; i++ {
		go func(x int) {
			cond.L.Lock()
			fmt.Println(x," 获取锁")
			defer cond.L.Unlock()
			cond.Wait()
			fmt.Println(x," 被唤醒")
			time.Sleep(time.Second)
		}(i)
	}


	time.Sleep(time.Second)
	fmt.Println("Signal...")
	cond.Signal()
	time.Sleep(time.Second)
	cond.Signal()
	time.Sleep(time.Second*3)
	cond.Broadcast()

	fmt.Println("Broadcast...")
	time.Sleep(time.Minute)
}

 

感谢:

https://blog.csdn.net/wentyoon/article/details/81174288

https://my.oschina.net/qiangmzsx/blog/1799695

你可能感兴趣的:(go小程序,Golang进阶)