c++中唯一锁、互斥锁和条件变量的关系
Relationship of unique lock, mutex and condition variable in c++
您好,我有以下代码:
// 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() 来调用 notify_all() 所以线程不会唤醒但是为什么打印函数“10 个线程准备好比赛......”没有也被调用?
另外,请解释一下为什么我需要调用 std::unique_lock lock(mtx);在 go() 函数中。谢谢大家!
顺便说一句,我在以下位置找到了这个示例:http://www.cplusplus.com/reference/condition_variable/condition_variable/
标准输出被缓冲。这意味着每个输出操作不是单独发送给父进程,而是聚集在内存中并批量发送。这样做是为了最大限度地减少系统调用/进程间通信的开销——或者输出所需的任何开销。
当缓冲区被填满时,它会被刷新,只有当它被刷新时你才能看到任何输出。显然 10 threads ready to race...
不足以填满缓冲区。
缓冲区也会在程序结束时刷新,或者在访问标准输入时刷新,或者如果您明确请求,使用 std::flush
或 std::endl
。
当您的程序无限期地等待其他线程(陷入死锁)时,它永远不会达到进一步填充缓冲区并最终刷新的程度。
您好,我有以下代码:
// 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() 来调用 notify_all() 所以线程不会唤醒但是为什么打印函数“10 个线程准备好比赛......”没有也被调用?
另外,请解释一下为什么我需要调用 std::unique_lock lock(mtx);在 go() 函数中。谢谢大家!
顺便说一句,我在以下位置找到了这个示例:http://www.cplusplus.com/reference/condition_variable/condition_variable/
标准输出被缓冲。这意味着每个输出操作不是单独发送给父进程,而是聚集在内存中并批量发送。这样做是为了最大限度地减少系统调用/进程间通信的开销——或者输出所需的任何开销。
当缓冲区被填满时,它会被刷新,只有当它被刷新时你才能看到任何输出。显然 10 threads ready to race...
不足以填满缓冲区。
缓冲区也会在程序结束时刷新,或者在访问标准输入时刷新,或者如果您明确请求,使用 std::flush
或 std::endl
。
当您的程序无限期地等待其他线程(陷入死锁)时,它永远不会达到进一步填充缓冲区并最终刷新的程度。