防止 C++ 中的交错
Posted
技术标签:
【中文标题】防止 C++ 中的交错【英文标题】:Preventing interleaving in C++ 【发布时间】:2014-08-18 18:25:43 【问题描述】:考虑以下示例类,它允许一个线程等待来自另一个线程的信号。
class Sync
std::mutex mtx, access;
std::condition_variable cv;
bool waiting;
public:
Sync()
: waiting(false)
Sync(const Sync&);
~Sync()
sendSignal();
void waitForSignal()
access.lock();
if (!waiting)
std::unique_lock<std::mutex> lck (mtx);
waiting = true;
access.unlock();
// in the time between these two statements, 'sendSignal()' acquires
// the lock and calls 'cv.notify_all()', thus the signal was missed.
cv.wait(lck);
else
access.unlock();
void sendSignal()
access.lock();
if (waiting)
std::unique_lock<std::mutex> lck (mtx);
cv.notify_all();
waiting = false;
access.unlock();
;
我遇到的问题是,在解锁“access”互斥锁和在 condition_variable 上调用“wait()”之间的时间间隔内,有时会因为交错而丢失信号。我怎样才能防止这种情况发生?
【问题讨论】:
看起来你需要一个条件变量。 我正在使用条件变量。 关键区域的堆栈溢出可能会有所帮助。 ***.com/questions/4434050/… @MadisonBrown 这个answer 提供了一个使用条件变量的信号量代理的合理实现。我认为 boost 的东西可以很容易地映射到适当的 c++11 特性。 您通常不想等待来自另一个线程的“信号”或任何其他瞬时事件——正是因为这样的事件很容易被错过。相反,您希望等待某些条件变为真(例如“数据可供读取”)。你检查条件,只有当它是假的时候才等待。然后,来自另一个线程的信号只是让您醒来并再次检查条件的一种手段。条件变量巧妙地封装了这种模式。 【参考方案1】:您可能应该只有一个互斥锁。我不明白您为什么需要访问权限。使用 mtx 保护 waiting 变量和条件变量。
类同步 std::mutex mtx; std::condition_variable 简历; 布尔等待; 上市: 同步() :等待(假) 同步(常量同步&); 〜同步() 发送信号(); 无效的等待信号() std::unique_lock lck (mtx); 如果(!等待) 等待=真; cv.wait(lck); 无效的发送信号() std::unique_lock lck (mtx); 如果(等待) cv.notify_all(); 等待=假; ;waiting 变量和条件变量 state 绑定在一起,因此应将它们视为单个临界区。
【讨论】:
以上是关于防止 C++ 中的交错的主要内容,如果未能解决你的问题,请参考以下文章