此问题与condition_variable.wait()函数有关。我认为通知它时可能不会立即锁定unique_lock。让我展示我的代码,您会更好地理解我的测试。

注意:编译器g++,std = c++ 14

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <atomic>
#include <future>

using namespace std;

mutex global_mut;
condition_variable global_cond;
atomic<bool> bval;
atomic<int> ival;

void accLock() {
  unique_lock<mutex> lock(global_mut);
  while (!bval.load()) {
    global_cond.wait(lock);
  }
  cout << __PRETTY_FUNCTION__ << " get the lock" << endl;
  ival.store(2, memory_order_release);
  lock.unlock();
}

void getVal() {
  lock_guard<mutex> lock(global_mut);
  cout << __PRETTY_FUNCTION__ << " get the lock with " << ival.load(memory_order_acquire) << endl;
}

int main(int argc, char** argv) {
  bval.store(false);
  ival.store(0, memory_order_release);

  // now my global_cond should be waiting for being notified
  std::future<void> fut = std::async(std::launch::async, accLock);

  // now my global_cond should be awaken and lock global_mut
  bval.store(true);
  global_cond.notify_one();

  // getVal should be waiting for global_mut to be unlocked
  getVal();
  return 0;
}

从概念上讲,我希望accLock线程先锁定互斥锁并更改ival,这样getVal()可以加载最新的ival,即2。我希望看到类似的输出

void accLock() get the lock
void getVal() get the lock with 2

但实际上,这是

void getVal() get the lock with 0
void accLock() get the lock

显然,此unique_lock并没有“立即”锁定global_cond,而是让lock_guard中的getVal()首先获取互斥量。
请问什么是实现我想要的正确方法?我对condition_variable正确理解吗?谢谢。

注意:
我使用memory_order_acl并发布,因为我认为这可以帮助我“更正”订单。但这是行不通的。

最佳答案

当两个线程争用一个互斥锁时,哪个线程可以获取它。如果您希望某件事在其他事情发生之前发生,那么您有义务编写代码以使该事情发生。互斥锁不会强制执行任何特定的顺序。

如果您不希望getVal在其他线程完成之前运行,则可以编写一些代码来等待它完成。您可以使用互斥量和条件变量来执行此操作,但是您没有。

一般而言,在您施加限制的前提下,实现会尽可能地高效。停止调用getVal的线程效率很低(因为其所有代码在缓存中都很热并且已经被调度),因此实现不执行该操作。

该实现没有办法知道您想要什么,并且低效率地做事情以希望这可能是您真正想要的但没有告诉您,这是没有意义的。

请注意,在以后的运行中,您可能会得到不同的结果。除非您使可运行的线程执行的顺序是不可预测的,否则它是不可预测的。都
线程已经准备好运行,因此您不能指望任何特别可靠的排序。在这种情况下,实现将是最佳的选择。

10-08 10:56