面试题答案
一键面试可能遇到的性能问题
- 虚假唤醒:在条件变量等待时,可能会出现没有相关条件变更却被唤醒的情况,导致不必要的计算和资源消耗。
- 唤醒效率低:当有大量等待的goroutine时,逐个唤醒或者广播唤醒可能导致性能瓶颈,特别是广播唤醒可能会唤醒很多实际不需要唤醒的goroutine。
优化方法
- 避免虚假唤醒
- 在唤醒后再次检查条件:在
Wait
返回后,通过if
语句再次检查条件,只有当条件真正满足时才执行相应操作。例如:
- 在唤醒后再次检查条件:在
cond.L.Lock()
for!condition() {
cond.Wait()
}
// 执行操作
cond.L.Unlock()
- **使用`sync.Cond`的`Signal`和`Broadcast`时,确保条件变更**:在调用`Signal`或`Broadcast`之前,保证相关条件确实发生了改变,以减少不必要的唤醒。
2. 提高唤醒效率
- 使用Signal
代替Broadcast
:如果明确知道只需要唤醒一个等待的goroutine,使用Signal
而不是Broadcast
。Signal
只会唤醒一个等待的goroutine,而Broadcast
会唤醒所有等待的goroutine,从而减少不必要的唤醒。
- 分组唤醒:可以根据业务逻辑,将goroutine进行分组,针对不同组的条件变更,使用不同的sync.Cond
实例进行唤醒,这样可以避免广播唤醒所有goroutine,只唤醒相关组的goroutine,提高唤醒效率。