请选择 进入手机版 | 继续访问电脑版

[Golang] Go语言中sync.Cond利用 详解

[复制链接]
查看131 | 回复28 | 2021-9-15 02:43:29 | 显示全部楼层 |阅读模式
目次

sync.Cond 可以用来干什么?

Golang 的 sync 包中的 Cond 实现了一种条件变量,可以利用 多个 Reader 等待公共资源。

每个 Cond 都会关联一个 Lock ,当修改条件或者调用 Wait 方法,必须加锁,保护 Condition。 有点类似 Java 中的 Wait 和 NotifyAll。

sync.Cond 条件变量是用来和谐 想要共享资源的那些 goroutine, 当共享资源的状态发生变化时,可以被用来关照 被互斥锁壅闭 的 gorountine。

与 Sync.Mutex 的区别

sync.Cond 基于互斥锁,和互斥锁有什么区别?

sync.Mutex 通常用来保护临界区和共享资源,条件变量 sync.Cond 用来和谐 想要访问的共享资源。

sync.Cond 利用 场景

有一个协程正在吸取 数据,其他协程必须等待这个协程吸取 完数据,才能读取到正确 的数据。

上述环境 下,假如 单纯的利用 channel 或者互斥锁,只能有一个协程可以等待,并读取到数据,没办法关照 其他协程也读取数据。

这个时间 怎么办?

  • 可以用一个全局变量标识第一个协程是否吸取 数据完毕,剩下的协程反复检查该变量的值,直到读取到数据。
  • 也可创建多个 channel, 每个协程壅闭 在一个 Channel 上,由吸取 数据的协程在数据吸取 完毕后,挨个关照 。

然后 Go 中着实 内置来一个 sync.Cond 来办理 这个标题 。

sync.Cond

  1. // Each Cond has an associated Locker L (often a *Mutex or *RWMutex),
  2. // which must be held when changing the condition and
  3. // when calling the Wait method.
  4. //
  5. // A Cond must not be copied after first use.
  6. type Cond struct {
  7. noCopy noCopy
  8. // L is held while observing or changing the condition
  9. L Locker
  10. notify notifyList
  11. checker copyChecker
  12. }
复制代码

可以看到每个 Cond 都会关联一个 锁 L (互斥锁 Mutex, 或者读写锁 * RMMutex), 当修改条件或者利用 Wait 的时间 必须要加锁。

sync.Cond 有哪些方法

NewCond 创建实例

  1. func NewCond(l Locker) *Cond
复制代码

NewCond 创建实例必要 关联一个锁。

详细 实例:

  1. cadence := sync.NewCond(&sync.Mutex{})
复制代码

Broadcast 广播唤醒全部

  1. // Broadcast wakes all goroutines waiting on c.
  2. //
  3. // It is allowed but not required for the caller to hold c.L
  4. // during the call.
  5. func (c *Cond) Broadcast()
复制代码

Broadcast 唤醒全部 等待条件变量 c 的 goroutine,无需锁保护。

详细 实例:

  1. go func() {
  2. for range time.Tick(1 * time.Millisecond) {
  3. cadence.Broadcast()
  4. }
  5. }()
复制代码

Signal 唤醒一个协程

  1. // Signal wakes one goroutine waiting on c, if there is any.
  2. //
  3. // It is allowed but not required for the caller to hold c.L
  4. // during the call.
  5. func (c *Cond) Signal()
复制代码

Signal 只唤醒恣意 1个等待条件变量 c 的 goroutine,无需锁保护。 有点类似 Java 中的 Notify

Wait 等待

  1. // Wait atomically unlocks c.L and suspends execution
  2. // of the calling goroutine. After later resuming execution,
  3. // Wait locks c.L before returning. Unlike in other systems,
  4. // Wait cannot return unless awoken by Broadcast or Signal.
  5. //
  6. // Because c.L is not locked when Wait first resumes, the caller
  7. // typically cannot assume that the condition is true when
  8. // Wait returns. Instead, the caller should Wait in a loop:
  9. //
  10. // c.L.Lock()
  11. // for !condition() {
  12. // c.Wait()
  13. // }
  14. // ... make use of condition ...
  15. // c.L.Unlock()
  16. //
  17. func (c *Cond) Wait()
复制代码

调用 Wait 会自动 开释 锁 c.L,并挂起调用者地点 的 goroutine,因此当前协程会壅闭 在 Wait 方法调用的地方。假如 其他协程调用了 Signal 或 Broadcast 唤醒了该协程,Wait 方法竣事 壅闭 时,并重新给 c.L 加锁,并且继续实行 Wait 后面的代码

代码示例:

  1. c.L.Lock()
  2. for !condition() {
  3. c.Wait()
  4. }
  5. ... make use of condition ...
  6. c.L.Unlock()
复制代码

代码示例

  1. package sync
  2. import (
  3. "log"
  4. "sync"
  5. "testing"
  6. "time"
  7. )
  8. var done = false
  9. func read(name string, c *sync.Cond) {
  10. c.L.Lock()
  11. for !done {
  12. c.Wait()
  13. }
  14. log.Println(name, "starts reading")
  15. c.L.Unlock()
  16. }
  17. func write(name string, c *sync.Cond) {
  18. log.Println(name, "starts writing")
  19. time.Sleep(time.Second)
  20. c.L.Lock()
  21. done = true
  22. c.L.Unlock()
  23. log.Println(name, "wakes all")
  24. c.Broadcast()
  25. }
  26. func TestSyncCond(t *testing.T) {
  27. cond := sync.NewCond(&sync.Mutex{})
  28. go read("reader1", cond)
  29. go read("reader2", cond)
  30. go read("reader3", cond)
  31. write("writer", cond)
  32. time.Sleep(time.Second * 3)
  33. }
复制代码

运行结果

  1. === RUN   TestSyncCond
  2. 2021/08/26 11:06:48 writer starts writing
  3. 2021/08/26 11:06:49 writer wakes all
  4. 2021/08/26 11:06:49 reader3 starts reading
  5. 2021/08/26 11:06:49 reader2 starts reading
  6. 2021/08/26 11:06:49 reader1 starts reading
  7. --- PASS: TestSyncCond (4.01s)
  8. PASS
复制代码

到此这篇关于Go语言中sync.Cond利用 详解的文章就先容 到这了,更多干系 Go sync.Cond内容请搜索 脚本之家从前 的文章或继续欣赏 下面的干系 文章盼望 大家以后多多支持脚本之家!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

avatar 疑骨德秋忘 | 2021-9-21 01:50:53 | 显示全部楼层
看帖、回帖、拿分、走人
回复

使用道具 举报

avatar 123457567 | 2021-9-21 23:49:51 | 显示全部楼层
admin楼主是我最崇拜的人!
回复

使用道具 举报

avatar 永远爱你冰塘 | 2021-9-29 10:22:47 | 显示全部楼层
宇宙第一贴诞生了!
回复

使用道具 举报

avatar 荷叶224 | 2021-10-6 03:57:42 | 显示全部楼层
admin楼主是一个典型的文艺青年啊!
回复

使用道具 举报

avatar 螃蟹357 | 2021-10-8 03:55:34 | 显示全部楼层
admin楼主的帖子越来越有深度了!
回复

使用道具 举报

avatar 醉于山水 | 2021-10-16 01:00:38 | 显示全部楼层
太邪乎了吧?
回复

使用道具 举报

avatar lang3344 | 2021-10-17 03:45:42 | 显示全部楼层
admin楼主就是我的榜样哦
回复

使用道具 举报

avatar 韶景于璃 | 2021-10-19 03:25:35 | 显示全部楼层
东方不败外加灭绝师太啊!
回复

使用道具 举报

avatar 恋恋青城黄 | 2021-10-19 04:55:00 | 显示全部楼层
好无聊啊!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则