C++临界区内是否需复制m_observers变量?必要性分析
为什么要复制
m_observers? 这步复制非常有必要,核心原因有三个:
缩短锁的持有时间,提升并发性能
要是直接遍历原m_observers,锁会从遍历开始一直持有到所有notifyEatingInitiated()调用完毕。如果某个观察者的回调函数执行耗时很长(比如涉及IO、阻塞操作),其他需要访问m_observers的线程就得一直等锁,严重拖慢并发效率。复制之后,锁只在复制容器的短时间内持有,遍历和调用回调的时候锁已经释放,其他线程可以正常操作原容器。避免迭代器失效与容器修改冲突
假设某个观察者的notifyEatingInitiated()回调里,间接调用了Animal类添加/删除观察者的方法(比如触发了某个逻辑要移除自己)。如果此时还持有锁且遍历原容器,修改原容器会直接导致迭代器失效,引发未定义行为。而遍历副本的话,原容器怎么修改都不会影响遍历过程。规避死锁风险
如果回调函数里尝试获取同一个m_mutex锁(比如调用Animal的其他需要加锁的成员函数),当前线程还持有锁的情况下就会触发死锁。复制完成后锁就释放了,回调里再获取锁就不会有这个问题。
另外补充:虽然锁确实能阻止外部修改m_observers,但锁的持有时间越短越好是并发编程的基本原则之一,复制容器就是实现这个目标的常用手段。
内容的提问来源于stack exchange,提问作者Ashish Kumar Jha
相关产品推荐
相关产品推荐

