Golang中的同步工具Sync.Cond详解

开发 前端
Sync.Cond需要与一个互斥锁或读写锁一起使用,以确保不会同时操作共享资源。当处于锁定状态时,Goroutine将阻塞在Wait()方法中,直到另一个Goroutine通过Broadcast()、Signal()方法发出通知信号。

sync.Cond

sync.Cond是Golang标准库提供的一个基于互斥锁/读写锁实现的条件变量类型,用于协调访问共享资源的多个goroutine。当共享资源状态发生变化时,可以通知等待条件变化而阻塞的goroutine。sync.Cond提供了一个创建方法和三个成员方法,如下:

  • NewCond(l Locker) ,创建Cond对象,需要传入一个锁对象,互斥锁或读写锁;
  • Wait(),阻塞当前goroutine,等待通知信号;
  • Signal(),发送信号通知,唤醒一个等待的goroutine;
  • Broadcast(),发送信号通知,唤醒多个等待的goroutine。

sync.Cond需要与一个互斥锁或读写锁一起使用,以确保不会同时操作共享资源。当处于锁定状态时,goroutine将阻塞在Wait()方法中,直到另一个goroutine通过Broadcast()、Signal()方法发出通知信号。

使用方法和示例

具体使用方法如下:

创建一个Mutex对象

var mutex = sync.Mutex{}

创建Cond对象,传入Mutex

cond := sync.NewCond(&mutex)

等待通知信号,阻塞当前goroutine

cond.Wait()

发送通知信号,唤醒一个或多个等待的goroutine

cond.Signal() // 唤醒一个goroutine
// 或者 cond.Broadcast() 唤醒多个goroutine

看一个示例:

package main

import (
	"log"
	"sync"
	"time"
)

func read(index int, c *sync.Cond) {
	c.L.Lock()
	c.Wait()
	log.Println(index, "开始读")
	c.L.Unlock()
}

func write(c *sync.Cond) {
	log.Println("开始写")
	time.Sleep(time.Second)
	log.Println("唤醒其中一个goroutine")
	c.Signal()
}

func main() {
	cond := sync.NewCond(&sync.Mutex{})

	for i := 1; i <= 5; i++ {
		go func(index int) {
			read(index, cond)
		}(i)
	}

	write(cond)

	time.Sleep(time.Second * 3)
}

输出内容如下:

2023/05/19 22:01:34 开始写
2023/05/19 22:01:35 唤醒其中一个goroutine
2023/05/19 22:01:35 2 开始读

可以看出,Signal()方法只唤醒了一个goroutine,可以把第二十行更改为c.Broadcast(),运行看下效果,会发现所有goroutine都被唤醒了。

小结

sync.Cond通过基于底层机制制定通知等待列表,在goroutine等待通知时将它添加到等待通知的列表中,然后通过Signal()或Broadcast()方法发出通知信号来唤醒等待的goroutine,实现条件变量和goroutine的通信和同步。

使用sync.Cond可以使并发编程更加高效和灵活,避免了使用time.Sleep()或者空for循环的一些缺点。但是,使用条件变量也需要小心使用,必须避免死锁和竞态条件等问题。

责任编辑:姜华 来源: 今日头条
相关推荐

2023-06-06 08:28:58

Sync.OnceGolang

2023-06-05 09:23:00

Golang同步工具

2021-05-21 08:21:57

Go语言基础技术

2021-07-06 07:46:07

Go语言编程

2023-11-28 08:01:48

互斥锁共享资源

2023-06-27 08:45:19

原子操作Golang

2023-05-11 08:00:44

Golangsync.Pool

2024-07-02 08:32:19

2010-05-19 10:22:07

2023-07-05 08:38:48

GolangGo语言

2023-12-25 09:58:25

sync包Go编程

2023-08-03 08:48:07

Golang接口

2023-03-30 07:52:03

Golang接口

2023-11-27 15:02:37

BytesGolang

2023-05-29 09:25:38

GolangSelect

2023-08-31 09:28:12

Golang可导出函数

2023-10-31 09:10:39

2023-06-09 08:16:09

GolangStruct Tag

2023-10-18 08:22:38

BufioGolang

2023-08-02 09:07:27

Golangio 包
点赞
收藏

51CTO技术栈公众号