这是一个普遍的问题.例如,当前有两个子线程已经调用pthread_cond_wait(&cond1,&mutex),它们都在等待.然后,父线程调用
pthread_cond_signal(&cond1);
pthread_cond_signal(&cond1);
Run Code Online (Sandbox Code Playgroud)
接下来,我的问题是,是否保证两个等待线程都会被唤醒?(假设第一个线程被唤醒,稍后在执行的某个阶段释放互斥,以便第二个线程可以获取它).
我提出这个问题的原因是,对于Unix系统级信号,信号(比如说SIGCHLD)不排队,因此如果连续传送多个相同类型的信号可能会丢失.所以我想知道是否有pthread_cond_signal不同的实现,以便如果调度程序碰巧让父线程连续两次发出信号,它们不会丢失?
我有一种情况,可以在wait()之前调用notify()'.
当我通过向他发送消息通知他时,我正在尝试制作一个模拟器来安排下一个事件.所以我设计了一个wait-> notify-> scedule链
void Broker::pause()
{
boost::unique_lock<boost::mutex> lock(m_pause_mutex);
{
std::cout << "pausing the simulation" << std::endl;
m_cond_cnn.wait(lock);
std::cout << "Simulation UNpaused" << std::endl;
// the following line causes the current function to be called at
// a later time, and a notify() can happen before the current function
// is called again
Simulator::Schedule(MilliSeconds(xxx), &Broker::pause, this);
}
}
void Broker::messageReceiveCallback(std::string message) {
boost::unique_lock<boost::mutex> lock(m_pause_mutex);
{
m_cond_cnn.notify_one();
}
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是:可能存在在调用wait()之前调用notify()的情况.
这种情况有解决方案吗?谢谢
我尝试在C++中开发一个线程池,我想知道在工作线程的主循环中产生()线程或者在条件变量上等待是否更好:
void worker_thread( void )
{
// this is more or less pseudocode
while( !done )
{
if( task_available )
run_task();
else
std::this_thread::yield();
}
}
Run Code Online (Sandbox Code Playgroud)
与
void worker_thread( void )
{
// this is more or less pseudocode
std::unique_lock< std::mutex > lk( mutex_ );
while( !done )
{
if( task_available )
run_task();
else
condition_.wait( lk );
}
}
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?两个版本之间是否会有任何性能差异?
假设
std::互斥锁和条件变量一起使用是否保证对不同类型的std::互斥锁和条件变量(除了构造它们)的操作不会抛出任何异常(特别是类型std::system_error)?
例如,在以下方法的情况下:
void MyClass::setVariable() {
std::lock_guard<std::mutex> const guard(m_mutex);
m_var = 42; // m_var is of type int
m_conditionVariable.notify_all();
}
void MyClass::waitVariable() {
std::unique_lock<std::mutex> lock(m_mutex);
m_conditionVariable.wait(lock, [this]() noexcept { return m_var == 42; });
}
Run Code Online (Sandbox Code Playgroud)
是否可以安全地假设noexcept或者应该在呼叫者周围写一些try-catch块?或者有任何警告吗?
请考虑C++ 11,C++ 14及更高版本中所有类型的互斥锁和条件变量.
我想在前面推出新主题,只要工作worker_thread已经开始,但也许结束.我用时间延迟替换了开始和结束的工作.我的代码是:
#include <iostream>
#include <string>
#include <mutex>
#include <condition_variable>
#include <future>
#include <atomic>
#include <chrono>
#include <thread>
std::mutex m;
std::condition_variable cv;
bool started = false;
void worker_thread()
{
std::unique_lock<std::mutex> lk(m);
static std::atomic<int> count(1);
std::this_thread::sleep_for(std::chrono::milliseconds{(count % 5) * 100});
std::cerr << "Start Worker thread: " << count << "\n";
started = true;
lk.unlock();
cv.notify_one();
std::this_thread::sleep_for(std::chrono::milliseconds{3000});
std::cerr << "Exit Worker thread: " << count << "\n";
++count;
}
int main()
{
while(1) {
std::async(std::launch::async, worker_thread);
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, …Run Code Online (Sandbox Code Playgroud) 我尝试包含std::condition_variable作为类成员,并在将此类的对象传递给a时遇到大量编译错误std::thread.我从我的实际程序中删除了所有其他代码,最后得到了以下最小代码.删除std::condition_variable原因没有问题.我尝试在构造函数中"初始化"变量,以及制作它inline,但都没有帮助.
#include <thread>
#include <condition_variable>
struct ThreadHandler {
void operator()() { }
std::condition_variable cond;
};
int main() {
ThreadHandler th1;
std::thread t1(th1);
t1.join();
}
Run Code Online (Sandbox Code Playgroud)
我在这做错了什么?
以下是我得到的编译错误:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread: In instantiation of ‘static std::thread::_Invoker<std::tuple<typename std::decay<_Tp>::type, typename std::decay<_Args>::type ...> > std::thread::__make_invoker(_Callable&&, _Args&& ...) [with _Callable = ThreadHandler&; _Args = {}; typename std::decay<_Tp>::type = ThreadHandler]’:
/usr/local/include/c++/8.1.0/thread:127:22: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = ThreadHandler&; _Args = {}]’
main.cpp:14:23: required from …Run Code Online (Sandbox Code Playgroud) Linux编程接口书有一段代码(生产者/消费者)来展示条件变量的工作原理:
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static int avail = 0;
while (TRUE) {
s = pthread_mutex_lock(&mtx);
while (avail == 0) { /* Wait for something to consume */
s = pthread_cond_wait(&cond, &mtx);
}
while (avail > 0) { /* Consume all available units */
avail--;
}
s = pthread_mutex_unlock(&mtx);
}
Run Code Online (Sandbox Code Playgroud)
为什么我们用pthread_mutex_lock的while?为什么我们不用它if?
来自维基百科关于投票的文章
计算机科学中的轮询或轮询操作是指客户端程序将外部设备的状态作为同步活动进行主动采样.轮询最常用于输入/输出(I/O),也称为轮询I/O或软件驱动的I/O.
轮询有时与忙等待轮询(忙等待)同义.在这种情况下,当需要I/O操作时,计算机除了检查I/O设备的状态之外什么都不做,直到它准备就绪,此时访问设备.换句话说,计算机等待设备准备就绪.
轮询还指的是重复检查设备是否准备就绪的情况,如果不是,则计算机返回到不同的任务.尽管不像繁忙等待那样浪费CPU周期,但这通常不如轮询,中断驱动I/O的替代方案那样有效.
因此,当一个线程不使用"条件变量"时,它会被称为"轮询"数据更改还是"忙等待"?
我试图了解在互斥锁用于条件变量时会发生什么.
在以下示例中,取自cppreference
int main()
{
std::queue<int> produced_nums;
std::mutex m;
std::condition_variable cond_var;
bool done = false;
bool notified = false;
std::thread producer([&]() {
for (int i = 0; i < 5; ++i) {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::unique_lock<std::mutex> lock(m);
std::cout << "producing " << i << '\n';
produced_nums.push(i);
notified = true;
cond_var.notify_one();
}
done = true;
cond_var.notify_one();
});
std::thread consumer([&]() {
std::unique_lock<std::mutex> lock(m);
while (!done) {
while (!notified) { // loop to avoid spurious wakeups
cond_var.wait(lock);
}
while (!produced_nums.empty()) {
std::cout << "consuming …Run Code Online (Sandbox Code Playgroud) 我正在使用condition_variableVisual Studio 2019。该condition_variable.wait_for()函数在std::cv_status::no_timeout没有任何通知的情况下返回。
#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
std::condition_variable cv;
std::mutex mtx;
bool called = false;
void printThread()
{
std::unique_lock<std::mutex> lck(mtx);
while (std::cv_status::timeout == cv.wait_for(lck, std::chrono::seconds(1)))
{
std::cout << "*";
}
std::cout << "thread exits" << std::endl;
}
int main()
{
std::thread th(printThread);
th.join();
std::cout << "program exits" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我认为代码永远不会退出并继续打印*,但在打印一些*.
这是输出:
********************************************************************thread exits
program exits
Run Code Online (Sandbox Code Playgroud)
为什么会发生这种情况?难道就是所谓的“虚假唤醒”?