• Go 语言中的 Cond 机制详解


    概述

    并发编程中,条件同步是一个常见的需求。Go 语言提供了 sync.Cond 类型来满足这一需求。sync.Cond 基于互斥锁sync.Mutex)提供了条件变量的同步机制,允许一组 goroutine 在满足某个条件时进行阻塞等待,或者在条件不再满足时被唤醒。

    核心概念

    • 互斥锁(Mutex)sync.Cond 内部使用了一个互斥锁来保证操作的原子性。
    • 条件变量(Cond):条件变量是一个同步机制,用于阻塞一组 goroutine 直到某个条件成立。
    • 等待(Wait):当条件不满足时,goroutine 会调用 Wait 方法进入等待状态。
    • 通知(Signal):当条件可能已经满足时,可以调用 SignalBroadcast 方法来唤醒一个或所有等待的 goroutine。

    使用步骤

    1. 初始化 Cond:创建一个 sync.Cond 实例,通常需要传入一个 sync.Mutexsync.RWMutex

      cond := sync.NewCond(&sync.Mutex{})
      
      • 1
    2. 等待条件:在条件不满足时,goroutine 会进入等待状态,释放互斥锁,并阻塞。

      cond.L.Lock() // 进入临界区
      defer cond.L.Unlock()
      for !condition {
          cond.Wait() // 等待条件满足
      }
      // 执行条件满足后的操作
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    3. 通知等待者:当条件满足时,需要通知等待的 goroutine。

      cond.Signal() // 唤醒一个等待的 goroutine
      // 或者
      cond.Broadcast() // 唤醒所有等待的 goroutine
      
      • 1
      • 2
      • 3

    示例

    以下是一个使用 sync.Cond 的简单示例,模拟了一个生产者-消费者问题:

    package main
    
    import (
    	"fmt"
    	"sync"
    	"time"
    )
    
    func main() {
    	var m sync.Mutex
    	var cond *sync.Cond = sync.NewCond(&m)
    	var count int
    
    	// 消费者 goroutine
    	go func() {
    		for {
    			m.Lock()
    			for count < 5 {
    				cond.Wait() // 等待条件满足
    			}
    			fmt.Println("Consumed:", count)
    			count--
    			m.Unlock()
    			time.Sleep(1 * time.Second)
    		}
    	}()
    
    	// 生产者 goroutine
    	go func() {
    		for i := 0; i < 10; i++ {
    			m.Lock()
    			for count >= 5 {
    				cond.Wait() // 等待条件满足
    			}
    			count++
    			fmt.Println("Produced:", i+1)
    			m.Unlock()
    			cond.Signal() // 通知消费者
    			time.Sleep(1 * time.Second)
    		}
    	}()
    
    	time.Sleep(20 * time.Second)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    注意事项

    • 死锁:在使用 sync.Cond 时,如果不恰当地使用互斥锁,可能会导致死锁。
    • 竞态条件:确保在调用 WaitSignalBroadcast 前正确地持有互斥锁。
    • 并发安全sync.Cond 并不是完全并发安全的,它依赖于外部的互斥锁来保证并发安全。

    结论

    sync.Cond 是 Go 语言中处理条件同步的有效工具。通过合理使用 sync.Cond,可以编写出高效且易于理解的并发代码。然而,正确地使用它需要对并发编程有深入的理解,以避免常见的并发问题,如死锁和竞态条件。

  • 相关阅读:
    皕杰报表之隐藏处理
    Git实战技巧-查看不同版本之间的差异和代码的改动
    【前端优化 & Vue项目优化】 如何避免浏览器卡顿,实现性能优化cdn?
    免备案海外服务器有什么好处?
    uniapp项目实践总结(二十四)安卓平台 APP 打包教程
    AngularJS实战之依赖注入与应用实践
    31、CSS进阶——@规则
    在PHP8中使用instanceof操作符检测对象类型-PHP8知识详解
    itext生成pdf
    文字太多时给文本框添加滑动条——text + ContentSizeFitter + Scroll View
  • 原文地址:https://blog.csdn.net/weixin_39801169/article/details/136653070