Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 条件变量的常见用例场景_C++_Multithreading_Synchronization_C++11 - Fatal编程技术网

C++ 条件变量的常见用例场景

C++ 条件变量的常见用例场景,c++,multithreading,synchronization,c++11,C++,Multithreading,Synchronization,C++11,条件变量可用于向其他线程发出发生了某些事情的信号: mutex m; condition_variable cv; thread t1([&cv]{ // processing ... cv.notify_one(); }); ... unique_lock<std::mutex> lck(m); cv.wait(lck); mutexm; 条件变量cv; 螺纹t1([&cv]{ //加工 ... cv.通知_one(); }); ... 唯一锁定

条件变量可用于向其他线程发出发生了某些事情的信号:

mutex m;
condition_variable cv;

thread t1([&cv]{
    // processing
    ...
    cv.notify_one();
});
...
unique_lock<std::mutex> lck(m);
cv.wait(lck);
mutexm;
条件变量cv;
螺纹t1([&cv]{
//加工
...
cv.通知_one();
});
...
唯一锁定lck(m);
cv.等待(lck);
但是正如您所看到的,在我们等待被通知之前,有一个机会窗口,线程处理已经完成,通知正在通过,所以我们将永远等待

在这种情况下,常见的解决方案是使用标志:

mutex m;
condition_variable cv;
bool done = false;

thread t1([&cv,&done]{
    // processing
    ...
    done = true; 
    cv.notify_one();
});
...
unique_lock<std::mutex> lck(m);
cv.wait(lck, [&done]{return done;});
mutexm;
条件变量cv;
bool done=false;
线程t1([&cv,&done]{
//加工
...
完成=正确;
cv.通知_one();
});
...
唯一锁定lck(m);
cv.wait(lck,[&done]{return done;});

使用标志是使用
条件变量的常见方式吗?还是我的解释有误?

通常在一个线程检测到它无法继续并决定等待某个条件(在英语意义上)得到满足的情况下使用
条件变量。
condition\u变量
本身并不是通知线程应该继续的主要机制,而是通知如果有线程正在等待,它应该重新检查,因为状态可能已经更改,现在可以继续了

最简单的示例之一是生产者/消费者队列,其中消费者将有如下代码:

void consume() {
   empty.wait( [&] { return !queue.empty(); } );
   // extract data from the queue and consume it here
}
也就是说,线程不仅仅在等待
条件_变量
变量,而是在等待对象的状态使线程能够继续。类似地,通知
条件_变量
并不是告诉另一个线程继续,只是通知任何等待条件满足的线程重新测试,因为状态可能已更改


回到您的用例,如果您的线程继续需要满足的条件是另一个线程已完成,那么使用这样的标志是完全正确的。

条件变量应始终与某个条件相关联,您应该测试:

unique_lock<mutex> lck(m); while (!something) cv.wait(lck); (在简单的情况下,我发现显式
循环更容易阅读。)


正在使用的条件变量可以看作是由条件变量、互斥体和谓词组成的3元组,它们通过一起使用来等待条件变量而在概念上绑定在一起。特定条件变量对象上的所有并发等待必须使用相同的互斥量,并且通常也将在相同的谓词(或依赖于相同数据、受相同互斥量保护的相关谓词)上等待。

a
condition\u variable
不是信号量,用例是/可以是不同的,用法也不同。您可以使用互斥体和条件变量模拟信号量,这就是您使用
done
标志所做的:模拟二进制信号量,我把它看作是一个信号量。有没有任何例子,我会使用一个没有标志或某种条件的条件变量?@IonTodirel,我想不出来。在我遇到的所有用例中,都有一些基本条件决定了等待的必要性;如果你没有“某种类型的标志或条件”,那么你就缺少了使用condvar所需的三分之一的成分(至少是为了正确和安全地使用它)。有趣的是,我很好奇为什么
wait
,在
condition\u variable
上,有一个不带谓词的重载,这可能是为了灵活性和放松在C++11之前实现条件变量的设计库通常只有重载,但事实是使用这些库的代码(boost::thread更接近)最终看起来都是一样的:
while(condition)condition\u variable.wait()
,这就是为什么他们添加了带函子的重载。注意,在lambdas之前,编写函子并不是那么容易。对于lambdas,新的重载是有意义的,但对于一些简单的情况,它可能没有意义,而一个简单的
while(!done)cond.wait()
可能比编写lambda更简单。请注意,您的示例相当于
wait
Yes的谓词版本,但正如我编辑它所显示的,读取谓词重载并不总是更容易 unique_lock<mutex> lck(m); cv.wait(lck, [&] { return something; });