返回顶部
首页 > 资讯 > 精选 >Go中Sync.Cond的介绍和使用
  • 586
分享到

Go中Sync.Cond的介绍和使用

2023-06-15 12:06:34 586人浏览 薄情痞子
摘要

本篇内容介绍了“Go中Sync.Cond的介绍和使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 程序中的通信方式GO语言中有句名言:

本篇内容介绍了“Go中Sync.Cond的介绍和使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

1. 程序中的通信方式

GO语言中有句名言:“不要用共享内存来通信,而是使用通信来共享内存”。

编程语言中,通信方式分为进程间通信、线程间通信。

进程间通信,常用方式:

线程间通信,常用方式:

  • 信号量

  • 互斥

  • 条件变量

对于Go语言来说,Go程序启动之后对外是一个进程,内部包含若干协程,协程相当于用户态轻量级线程,所以协程的通信方式大多可以使用线程间通信方式来完成。

协程间通信方式,官方推荐使用channel,channel在一对一的协程之间进行数据交换与通信十分便捷。但是,一对多的广播场景中,则显得有点无力,此时就需要sync.Cond来辅助。

2. 什么是广播?

举个例子,上高中时,宿管老师每天早晨需要叫醒学生们去上课。这个时候,有两种解决方法:①一个寝室一个寝室的把学生叫醒。②在宿舍楼安装个广播,到起床时间时,在广播上叫醒学生。显然,使用广播的方式效率更高。

编程中的广播可以理解为:多个操作流程依赖于一个操作流程完成后才能进行某种动作,这个被依赖的操作流程在唤醒所有依赖者时使用的一种通知方式。

在Go语言中,则可以使用sync.Cond来实现多个协程之间的广播通知功能。

3. sync.Cond

cond是sync包下面的一种数据类型,相当于线程间通信的条件变量方式。

// Cond implements a condition variable, a rendezvous point // for goroutines waiting for or announcing the occurrence // of an event. // // Each Cond has an associated Locker L (often a *Mutex or *RWMutex), // which must be held when changing the condition and // when calling the Wait method. // // A Cond must not be copied after first use. type Cond struct {     noCopy noCopy  // 在第一次使用后不可复制,使用go vet作为检测使用      // L is held while observing or changing the condition   // 根据需求初始化不同的锁,如*Mutex 和 *RWMutex。注意是 指针类型     L Locker    // 具有头尾指针的链表。存储被阻塞的协程,通知时操作该链表中的协程     notify  notifyList     checker copyChecker  // 复制检查,检查cond实例是否被复制 }

该数据类型提供的方法有:

type Cond  func NewCond(l Locker) *Cond func (c *Cond) Broadcast() // 通知所有协程,广播 func (c *Cond) Signal()  // 通知一个协程 func (c *Cond) Wait()  // 阻塞等待,直到被唤醒

对应源码追溯

// Wait atomically unlocks c.L and suspends execution // of the calling goroutine. After later resuming execution, // Wait locks c.L before returning. Unlike in other systems, // Wait cannot return unless awoken by Broadcast or Signal. // // Because c.L is not locked when Wait first resumes, the caller // typically cannot assume that the condition is true when // Wait returns. Instead, the caller should Wait in a loop: //       //      注意下面的写法是官方推荐的 //    c.L.Lock() //    for !condition() { //        c.Wait() //    } //    ... make use of condition ... //    c.L.Unlock() // func (c *Cond) Wait() {     // 检查c是否是被复制的,如果是就panic     c.checker.check()     // 获取等待队列的一个ticket数值,作为唤醒时的一个令牌凭证     t := runtime_notifyListAdd(&c.notify)     // 解锁     c.L.Unlock()        // 注意,上面的ticket数值会作为阻塞携程的一个标识     // 加入通知队列里面     // 到这里执行gopark(),当前协程挂起,直到signal或broadcast发起通知     runtime_notifyListWait(&c.notify, t)        // 被唤醒之后,先获取锁     c.L.Lock() }  // Signal wakes one goroutine waiting on c, if there is any. // // It is allowed but not required for the caller to hold c.L // during the call. func (c *Cond) Signal() {     c.checker.check()     runtime_notifyListNotifyOne(&c.notify)  // 随机挑选一个进行通知,wait阻塞解除 }  // Broadcast wakes all goroutines waiting on c. // // It is allowed but not required for the caller to hold c.L // during the call. func (c *Cond) Broadcast() {     c.checker.check()     // 通知所有阻塞等待的协程     // 主要是唤醒 cond.notify 链表上的各个协程     runtime_notifyListNotifyAll(&c.notify) }

使用方法,代码示例:

var locker sync.Mutex var cond = sync.NewCond(&locker)  // NewCond(l Locker)里面定义的是一个接口,拥有lock和unlock方法。 // 看到sync.Mutex的方法,func (m *Mutex) Lock(),可以看到是指针有这两个方法,所以应该传递的是指针 func main() {     // 启动多个协程     for i := 0; i < 10; i++ {         gofunc(x int) {             cond.L.Lock()          // 获取锁             defer cond.L.Unlock()  // 释放锁                        cond.Wait()   // 等待通知,阻塞当前 goroutine                        // 通知到来的时候, cond.Wait()就会结束阻塞, do something. 这里仅打印             fmt.Println(x)         }(i)     }        time.Sleep(time.Second * 1) // 睡眠 1 秒,等待所有 goroutine 进入 Wait 阻塞状态     fmt.Println("Signal...")     cond.Signal()               // 1 秒后下发一个通知给已经获取锁的 goroutine        time.Sleep(time.Second * 1)     fmt.Println("Signal...")     cond.Signal()               // 1 秒后下发下一个通知给已经获取锁的 goroutine        time.Sleep(time.Second * 1)     cond.Broadcast()            // 1 秒后下发广播给所有等待的goroutine     fmt.Println("Broadcast...")     time.Sleep(time.Second * 1) // 等待所有 goroutine 执行完毕 }

 总结

在Go中协程间通信的方式有多种,最常用的是channel。如果牵扯多个协程的通知,可以使用sync.Cond。

查看channel、sync.Cond源码之后会发现,它们有相似之处:

  1. 阻塞协程统一被封装在 sudog 结构里面

  2. channel阻塞读/写时,用双向链表存储被阻塞导致等待唤醒的协程

  3. sync.Cond用带有头尾指针的单向链表存储被阻塞导致等待唤醒的协程

  4. 阻塞时都是使用gopark()进行协程的挂起操作

虽说有相似之处,但是却有本质区别:

  1. channel 可以用来在协程间传递数据

  2. sync.Cond 不可以在协程间传递数据,主要用来进行协程的阻塞唤醒操作。如果需要传递数据,则需要全局变量进行传递

“Go中Sync.Cond的介绍和使用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: Go中Sync.Cond的介绍和使用

本文链接: https://lsjlt.com/news/280127.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Go中Sync.Cond的介绍和使用
    本篇内容介绍了“Go中Sync.Cond的介绍和使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 程序中的通信方式GO语言中有句名言:...
    99+
    2023-06-15
  • Go语言中sync.Cond使用详解
    目录sync.Cond 可以用来干什么? 与 Sync.Mutex 的区别 sync.Cond 使用场景 sync.Cond sync.Cond 有哪些方法 NewCond 创建实例...
    99+
    2024-04-02
  • Go语言sync.Cond如何使用
    本篇内容介绍了“Go语言sync.Cond如何使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!基本使用1 定义sync.Cond是Go语言...
    99+
    2023-07-05
  • Redis中锁的介绍和使用
    其实说多线程修改数据也不合适,毕竟redis服务端是单线程的,所有命令串行执行,只是在客户端并发发送命令的时候,导致串行的命令一些排列问题和网络时间差等造成数据不一致。本文虽然是数字的加减,但是为了说明锁的...
    99+
    2024-04-02
  • Go并发编程sync.Cond的具体使用
    目录简介详细介绍案例:Redis连接池注意点简介 Go 标准库提供 Cond 原语的目的是,为等待 / 通知场景下的并发问题提供支持。Cond 通常应用于等待某个条件的一组 g...
    99+
    2022-06-07
    GO sync
  • Go并发编程sync.Cond怎么使用
    本篇内容主要讲解“Go并发编程sync.Cond怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Go并发编程sync.Cond怎么使用”吧!简介Go 标准库提供 Cond 原语的目的是,为...
    99+
    2023-06-30
  • Golang中的sync.Cond怎么使用
    本文小编为大家详细介绍“Golang中的sync.Cond怎么使用”,内容详细,步骤清晰,细节处理妥当,希望这篇“Golang中的sync.Cond怎么使用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1. 基本...
    99+
    2023-07-05
  • SVN介绍和使用
    文章目录 SVN的介绍SVN是什么作用 安装包下载SVN的使用检出提交显示日志更新 patch的使用创建使用 SVN的介绍 SVN是什么 SVN是subversion的缩写,是一个开放源代码的版本控制系统,通过采用分...
    99+
    2023-08-19
    svn
  • jwt介绍和PHP的使用
    适用于分布式单点登录(SSO) 流程 客户端输入账号密码登录; 服务端判断登录信息,用户登录成功返回客户端token; 客户端存储token,每个请求都需要传递token到服务端; 服务端验证token的有效期,返回对应的信息; 构成 分为...
    99+
    2023-10-20
    1024程序员节 php
  • 浅析Go汇编语法和MatrixOne使用介绍
    目录MatrixOne数据库是什么Go汇编介绍为什么使用Go汇编?为什么不用CGO?Go汇编语法特点操作数顺序寄存器宽度标识函数调用约定对写Go汇编代码有帮助的工具avotext/t...
    99+
    2024-04-02
  • redis中key命令的介绍和使用
    这篇文章将为大家详细讲解有关redis中key命令的介绍和使用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、概述:进入redis-cli之后,我们通常比较关心的是有哪...
    99+
    2024-04-02
  • Go语言中DateTime的用法介绍
    一、基本使用 ①从属于time这个包 ②一般使用都是使用 time.Time 这个类型表示时间 ,time包中还有一些常量,源码如下 // Common durations. The...
    99+
    2024-04-02
  • 【脚本】python中wmi介绍和使用
    一:WMI基础知识===================================================================WMI 最初于1998年作为一个附加组件与 Windows NT 4.0 Servic...
    99+
    2023-01-31
    脚本 python wmi
  • GO中的条件变量sync.Cond详解
    目录GO的条件变量一、条件变量与互斥锁二、条件变量与互斥锁的配合使用三、条件变量的使用四、条件变量的Wait方法做了什么GO的条件变量 一、条件变量与互斥锁 条件变量是基于互斥锁的,...
    99+
    2023-01-09
    go 条件变量sync.Cond go sync.Cond go 条件变量
  • redis命令的介绍和使用
    本篇文章展示了redis命令的语法介绍和使用,代码简明扼要容易理解,绝对能让你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Redis 命令用于在 redis 服务上执行操作。要在 redis 服务上执...
    99+
    2024-04-02
  • TKMybatis的介绍和使用详解
    目录一、什么是 TKMybatis二、TKMybatis 使用2.1 Springboot 项目中加入依赖2.2 使用讲解2.3 实际案例三、扩展介绍泛型(实体类)的类型必须符合要求...
    99+
    2024-04-02
  • redis中事务命令的介绍和使用
    这篇文章将为大家详细讲解有关redis中事务命令的介绍和使用,文章内容质量较高,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、概述:Redis 事务的本质是一组命令的集合。事务支持一次执...
    99+
    2024-04-02
  • Python中各个模块的介绍和使用
    北京 | 高性能计算之GPU CUDA课程11月24-26日3天密集学习 快速带你晋级阅读全文> 作者,许胜利,Python开发工程师,任职于上海某财富管理有限公司。 在Python中有一个概念叫做模块(module),这个和...
    99+
    2023-01-31
    模块 Python
  • Node.js中 __dirname 的使用介绍
    前言 本文主要给大家介绍的是关于Node.js中 __dirname 使用的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍: 方法如下 新建个文件 app.js 里面的内容如下: conso...
    99+
    2022-06-04
    Node js __dirname
  • Python中itertools简介使用介绍
    目录Python中itertools模块一、 简介二、 使用介绍1、 常用迭代器1.1 chain1.2 groupby2、 无穷迭代器2.1 count2.2 cycle2.3 r...
    99+
    2022-12-28
    Python中itertools Python itertools详解 Python itertools
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作