在 Go 语言中,条件变量(sync.Cond)提供的 Broadcast 方法与 Signal 方法在唤醒等待协程的行为上有何不同?请说明两者的区别及适用场景。
考察说明
考查对 Go 并发原语 sync.Cond 中 Broadcast 与 Signal 语义差异的理解。
回答思路
- 【回答框架 1】sync.Cond 是 Go 提供的条件变量,用于在多个协程间协调等待与通知。其核心方法包括 Wait、Signal 和 Broadcast。Signal 会唤醒一个正在等待该条件变量的协程,而 Broadcast 会唤醒所有等待的协程。
- 【回答框架 2】Signal 适用于只需一个等待者处理条件变化的场景,例如任务队列中仅需一个消费者处理新任务,可减少不必要的竞争。Broadcast 适用于条件变化会影响所有等待者的场景,例如共享状态更新后所有等待者都需要重新检查条件。
- 【回答框架 3】使用 Signal 时需注意,若多个协程等待不同条件,可能唤醒错误的协程导致死锁或延迟;Broadcast 则能确保所有等待者都被唤醒,但可能引起惊群效应,增加调度开销。
- 【回答框架 4】实际使用中,应结合条件判断循环(for 而非 if)来避免虚假唤醒,并在修改共享状态后调用 Broadcast 或 Signal 通知等待者。选择依据是等待者数量及条件变化的语义。
- 【回答框架 5】在 Go 中,sync.Cond 通常与互斥锁配合使用,Wait 会自动释放锁并挂起,被唤醒后重新获取锁。理解两者的区别有助于编写高效且正确的并发程序。
- 【关键点 1】Signal 唤醒一个等待协程,Broadcast 唤醒所有等待协程。
- 【关键点 2】Signal 适合单消费者场景,Broadcast 适合多消费者或条件影响所有等待者的场景。
- 【关键点 3】使用 for 循环检查条件以避免虚假唤醒,并确保在修改状态后正确通知。
- 【易错点 1】误用 Signal 可能导致某些等待者永远不被唤醒,尤其在多条件等待时。
- 【易错点 2】Broadcast 可能引起惊群效应,但通常比漏唤醒更安全。
- 【易错点 3】忽略条件变量的锁保护,直接调用 Wait 或 Signal 会导致数据竞争或死锁。