介绍

  1. Cond是一个条件锁,就是当满足某些条件下才起作用的锁,有的地方也叫定期唤醒锁,有的地方叫条件变量conditional variable。这个同步工具拿来与互斥锁一起讨论。实际上,条件变量是基于互斥锁的,它必须有互斥锁的支撑才能发挥作用。
  2. 条件变量并不是被用来保护临界区和共享资源的,它是用于协调想要访问共享资源的那些线程的。当共享资源的状态发生变化时,它可以被用来通知被互斥锁阻塞的线程.

    适用场景

  3. 条件变量在这里的最大优势就是在效率方面的提升。当共享资源的状态不满足条件的时候,想操作它的线程再也不用循环往复地做检查了,只要等待通知就好了

    1. 如:摄像头,这类共享资源同一时间内只允许一个人,你想用时发现已经有人在使用,你的选择可以是
      1. 一直在边上看着他,他放开了,立马去拿。
      2. 可以找个地方歇着,等别人用完后告诉你一声。

        源码阅读

  1. type Cond struct {
  2. noCopy noCopy
  3. // L is held while observing or changing the condition
  4. L Locker
  5. notify notifyList
  6. checker copyChecker
  7. }
  8. // NewCond returns a new Cond with Locker l.
  9. func NewCond(l Locker) *Cond {
  10. return &Cond{L: l}
  11. }
  1. 初始化
    • Cond 是通过 NewCond 来初始化
  2. 方法
  • 等待通知: wait
    • 阻塞当前线程,直到收到该条件变量发来的通知。wati前必须先 lock。
  • 单发通知: signal
    • 让该条件变量向至少一个正在等待它的通知的线程发送通知,表示共享数据的状态已经改变。
  • 广播通知: broadcast
    • 让条件变量给正在等待它的通知的所有线程都发送通知。

栗子

  1. func main() {
  2. var lc = new(sync.Mutex)
  3. var cond = sync.NewCond(lc)
  4. for i := 0; i < 3; i++ {
  5. go func(x int) {
  6. //竞争锁
  7. cond.L.Lock()
  8. //记得要释放锁
  9. defer cond.L.Unlock()
  10. cond.Wait()
  11. fmt.Println(x)
  12. }(i)
  13. }
  14. time.Sleep(2 * time.Second)
  15. cond.Signal()
  16. cond.Broadcast()
  17. time.Sleep(2 * time.Second)
  18. }

运行结果

  1. 0
  2. 2
  3. 1

感谢

https://www.jianshu.com/p/2dce206b6d79