golang sync.Cond同步机制运用及实现

 更新时间:2023年09月27日 10:35:36   作者:lincoln_hlf1  
在 Go 里有专门为同步通信而生的 channel,所以较少看到 sync.Cond 的使用,不过它也是并发控制手段里的一种,今天我们就来认识下它的相关实现,加深对同步机制的运用

sync.Cond

Go同步通信channel

sync.Cond 提供了三个方法:Wait()、Signal()、Broadcast(),它们的用法如下:

  • Wait():阻塞当前的 goroutine,等待唤起。
  • Signal():唤起一个阻塞的 goroutine。
  • Broadcast():唤起所有阻塞的 goroutine。

通过上面的方法描述,我们就可以简单的实现一个任务池功能:先批量的创建 goroutine,然后调用 sync.Cond 的 Wait() 方法让其阻塞的等待。

当有一个任务到来时,则通过 Signal() 唤起刚刚在阻塞的某一个 goroutine,去执行任务。

通过任务池功能,我们发现 sync.Cond 的运用很简单,但 Go 官方并不推荐我们使用 sync.Cond 来实现协程间的同步通信

因为它并不符合 Go 官方 “通过通信来共享内存” 的设计思想,当场景复杂时,则会耦合各个业务功能。

sync.Cond 源码分析

我们来看下 sync.Cond 的结构体,代码在 /sr/sync/cond.go 下:

type Cond struct {
    noCopy noCopy       // 不可复制
    L Locker            // 锁
    notify  notifyList  // 通知唤起列表
    checker copyChecker // 复制检测
}

可以看到 Cond 上有 notify 列表,而这正是维护了需要唤起的 goroutine 列表。

当我们调用 Wait() 方法的时候就会维护当前 goroutine 到对应的 notifyList 里:

func (c *Cond) Wait() {
    c.checker.check()
    t := runtime_notifyListAdd(&c.notify) // 将当前 goroutine 添加到 notifyList 里
    c.L.Unlock()
    runtime_notifyListWait(&c.notify, t) // 阻塞等待
    c.L.Lock()
}

当有其他协程调用了 Signal 或 Broadcast 方法时,则会通过runtime_notifyListNotifyOneruntime_notifyListNotifyAll方法来唤起一个或多个 goroutine。

其他同步方式的实现

前面提到到 sync.Cond 并不被推荐作为协同通信手段,那如果要实现它的单播、广播效果,该怎么弄呢?

其实也很简单,如果我们要实现单播效果,那么只需要通过阻塞的监听 channel 信号即可。

如果要实现广播唤起效果,只需要利用 context 的链式取消特性,也能达到该效果。

以上就是golang sync.Cond同步机制运用及实现的详细内容,更多关于golang sync.Cond同步机制的资料请关注脚本之家其它相关文章!

相关文章

  • Golang urfave/cli库简单应用示例详解

    Golang urfave/cli库简单应用示例详解

    这篇文章主要为大家介绍了Golang urfave/cli库简单应用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • golang通过context控制并发的应用场景实现

    golang通过context控制并发的应用场景实现

    这篇文章主要介绍了golang通过context控制并发的应用场景实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • 向Rust学习Go考虑简单字符串插值特性示例解析

    向Rust学习Go考虑简单字符串插值特性示例解析

    这篇文章主要为大家介绍了向Rust学习Go考虑简单字符串插值特性示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02
  • go语法入门any类型的使用场景示例详解

    go语法入门any类型的使用场景示例详解

    这篇文章主要为大家介绍了go语法入门any类型的使用场景示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • 通过Golang实现无头浏览器截图

    通过Golang实现无头浏览器截图

    在Web开发中,有时需要对网页进行截图,以便进行页面预览、测试等操作,本文为大家整理了Golang实现无头浏览器的截图的方法,感兴趣的可以了解一下
    2023-05-05
  • golang DNS服务器的简单实现操作

    golang DNS服务器的简单实现操作

    这篇文章主要介绍了golang DNS服务器的简单实现操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • go语言中的二维切片赋值

    go语言中的二维切片赋值

    这篇文章主要介绍了go语言中的二维切片赋值操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • golang 删除切片的某个元素及剔除切片内的零值方式

    golang 删除切片的某个元素及剔除切片内的零值方式

    这篇文章主要介绍了golang 删除切片的某个元素及剔除切片内的零值方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Golang分布式锁简单案例实现流程

    Golang分布式锁简单案例实现流程

    分布式锁是控制分布式系统之间同步访问共享资源的一种方式。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源时,需要通过一些互斥手段来防止彼此之间的干扰以保证一致性,在这种情况下,就需要使用分布式锁了
    2022-12-12
  • go语言通过管道连接两个命令行进程的方法

    go语言通过管道连接两个命令行进程的方法

    这篇文章主要介绍了go语言通过管道连接两个命令行进程的方法,实例分析了Go语言操作命令行进程的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-03-03

最新评论