c++ - 通知线程是否总是需要在修改期间锁定共享数据?

标签 c++ multithreading c++11 mutex condition-variable

使用条件变量时,http://en.cppreference.com/w/cpp/thread/condition_variable将通知线程的典型步骤描述为:

  1. acquire a std::mutex (typically via std::lock_guard)
  2. perform the modification while the lock is held
  3. execute notify_one or notify_all on the std::condition_variable (the lock does not need to be held for notification)

下面这个简单的例子,主线程在修改的时候是否需要锁定“stop”?虽然我知道在修改共享数据时锁定几乎总是一个好主意,但我不确定为什么在这种情况下有必要。

std::condition_variable cv;
std::mutex mutex;
bool stop = false;

void worker() {
    std::unique_lock<std::mutex> lock(mutex);
    cv.wait(lock, [] { return stop; })
}

// No lock (Why would this not work?)
void main() {
     std::thread(worker);
     std::this_thread::sleep_for(1s);
     stop = true;
     cv.notify_one();
}

// With lock: why is this neccesary?
void main() {
     std::thread mythread(worker);
     std::this_thread::sleep_for(1s);
     {
         std::unique_lock<std::mutex>(mutex);
         stop = true;
     }
     cv.notify_one();
     mythread.join();
}

最佳答案

For the simple case shown below, is it necessary for the main thread to lock "stop" when it modifies it?

是的,为了防止竞争条件。除了可以通过 std::atomic 解决的从不同线程访问共享数据的问题之外,想象一下以下事件顺序:

worker_thread: checks value of `stop` it is false
main_thread: sets `stop` to true and sends signal
worker_thread: sleeps on condition variable

在这种情况下,工作线程可能会永远休眠并且它会错过 stop 设置为 true 的事件,这仅仅是因为唤醒信号已经发送但它错过了。

在修改共享数据时获取互斥量是必需的,因为只有这样你才能将检查条件并进入休眠状态或在工作线程中对其进行操作作为一个整体的原子操作。

关于c++ - 通知线程是否总是需要在修改期间锁定共享数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47356463/

相关文章:

c++ - 如何计算 ScreenToWorld 坐标?

java - 在 JUnit 测试之前我应该​​如何启动服务器?

C++如何调用带参数的线程

java - 如何使用线程池为生产者-消费者解决方案创建动态消费者任务?

c++ - 在 C# 中连接到 Websphere MQ 有效,但在 C++ 中失败,代码为 2058 (MQRC_Q_MGR_NAME_ERROR)

c++ - 使用可变参数模板将 vector 中的参数应用于函数时出现奇怪错误

c++ - 从 ‘void* (*)()’ 到 ‘void* (*)(void*)’ [-fpermissive] 的无效转换

c++ - 如何在 kdevelop 中设置 llvm?

c++ - 定义重复的异常规范是否合法

c++ - 在模板函数参数中使用 std::bind