c++ - C++中唯一锁、互斥量和条件变量的关系

标签 c++ multithreading locking mutex condition-variable

您好,我有以下代码:

// condition_variable example
#include <iostream>           // std::cout
#include <thread>             // std::thread
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void print_id (int id) {
  std::unique_lock<std::mutex> lock(mtx);
  while (!ready) cv.wait(lock);
  // ...
  std::cout << "thread " << id << '\n';
}

void go() {
  std::unique_lock<std::mutex> lock(mtx);
  ready = true;
  cv.notify_all();
}

int main ()
{
  std::thread threads[10];
  // spawn 10 threads:
  for (int i=0; i<10; ++i)
    threads[i] = std::thread(print_id,i);

  std::cout << "10 threads ready to race...\n";
  //go();                       // go!

  for (auto& th : threads) th.join();
  std::cout << "Finished!" << std::endl;

  return 0;
}

如果我删除 main 中函数调用 go() 的注释,我会得到以下输出:

10 threads ready to race...
thread 0
thread 8
thread 1
thread 2
thread 4
thread 5
thread 3
thread 6
thread 7
thread 9
Finished!

我完全理解为什么我会得到这个输出的一些流程。但是,我不明白为什么如果我注释掉 main 中的 go() 函数调用,我无法打印“10 个线程准备竞赛...”。如果我理解正确的话,我没有通过不调用 go() 来调用 notification_all(),因此线程不会唤醒,但为什么打印函数“10 个线程准备好竞赛...”也没有被调用?

另外,请解释一下为什么我需要调用 std::unique_lock lock(mtx);在 go() 函数内部。谢谢大家!

顺便说一句,仅供引用,我在以下位置找到了这个示例:http://www.cplusplus.com/reference/condition_variable/condition_variable/

最佳答案

标准输出被缓冲。这意味着每个输出操作不会单独发送到父进程,而是聚集在内存中并批量发送。这样做是为了最大限度地减少系统调用/进程间通信的开销 - 或任何输出所需的开销。

当缓冲区被填满时,它将被刷新,并且只有当它被刷新时你才能看到任何输出。显然 10 个线程准备好竞争... 不足以填充缓冲区。

当程序结束时,或者当访问标准输入时,或者如果您使用 std::flushstd::endl 显式请求时,缓冲区也会被刷新。

当您的程序无限期地等待其他线程(处于死锁状态)时,它永远不会达到缓冲区被进一步填充并最终刷新的程度。

关于c++ - C++中唯一锁、互斥量和条件变量的关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42713008/

相关文章:

c++ - 如何在 C++ 中使用 tcp_diag?

来自修改后的集合的 Java 8 流

java - 多条件 vs 多锁

sql-server-2005 - ORDER BY 和 WITH(ROWLOCK、UPDLOCK、READPAST)

需要 Android App Locker 密码

c++ - 为什么数组*新数组;在 C++ 中失败?

c++ - 显示没有总和的迭代数字

c++ - 如何找到 vector 中的元素?

java - 线程安全读/写计数器

python - 以关键字参数作为线程启动方法