请考虑以下代码:
int main() {
bool done = false;
condition_variable con;
mutex m;
thread producer([&]() {
this_thread::sleep_for(chrono::seconds(10));
done = true;
//con.notify_one();
});
thread consumer([&]() {
/*unique_lock<mutex> lock(m);
while (!done) {
con.wait(lock);
}*/
while (!done);
cout << "now my turn..."<<endl;
});
producer.join();
consumer.join();
}
Run Code Online (Sandbox Code Playgroud)
如果我取消注释2个线程中的代码,我将使用condition_variable.所以消费者线程看起来像这样:
thread consumer([&]() {
unique_lock<mutex> lock(m);
while (!done) {
con.wait(lock);
}
// while (!done); <-this is equivalent of the above
cout << "now my turn..."<<endl;
});
Run Code Online (Sandbox Code Playgroud)
似乎我可以使用/不使用condition_variable来实现相同的功能.所以我的问题是:如果已经使用了通知变量(在这种情况下为'done'变量),为什么我们需要condition_variable?使用它有什么好处?我可以做一些通知变量不能做的事吗?
这是我第一次使用 WINAPI 以及SleepConditionVariableCS、WakeConditionVariable、WaitForMultipleObjects和InitializeConditionVariable等函数,Eclipse IDE 告诉我它们没有在此范围内声明。
据推测,它们都包含在同一个 lib windows.h中,所以我不知道出了什么问题,因为ExitThread、ReleaseSemaphore和WaitForSingleObject等其他函数正在运行,没有任何问题。
可能是我的c++版本有问题?或者是否存在任何其他库可以包含?
谢谢
我正在为我的项目构建一个多线程服务器.
我正在使用条件变量和锁.
我将条件变量cv作为全局,将mutex _mtxReceivedMessages作为类成员.
这是等待用户消息的功能:
void Server::handleReceivedMessages()
{
while (1)
{
std::unique_lock<std::mutex> lck(_mtxReceivedMessages);
while (_queRcvMessages.size() == 0) cv.wait(lck); // As long as there are 0 messages in the queue
}
}
Run Code Online (Sandbox Code Playgroud)
这是调用通知cv的函数:
void Server::addReceivedMessage(ReceivedMessage* msg)
{
_queRcvMessages.push(msg); // Adds the message to the queue
cv.notify_all(); // Unlockes all locked functions
}
Run Code Online (Sandbox Code Playgroud)
问题是,如果我尝试在函数handleReceivedMessages等待时关闭程序(在调用函数addReceivedMessage之前)程序崩溃,
但是如果我删除该行:
while (_queRcvMessages.size() == 0) cv.wait(lck); // As long as there are 0 messages in the queue
Run Code Online (Sandbox Code Playgroud)
程序退出就好了.
程序崩溃:Nuvola.exe中0x7748507C(ntdll.dll)的未处理异常:0xC000000D:将无效参数传递给服务或函数.
可能是什么问题?
我用conditional_variable::notify_all()唤醒一个等待的线程(只有一个线程在等待unique_lock 确实)。
这个代码片段在大多数情况下都运行良好,但日志文件(详细信息见下文)表明unique_lock在新创建的线程已经返回后,父线程无法获取。
我将不胜感激能在这个问题上得到一些帮助。
这是相关的代码片段:
void MainWindow::deployAction(void)
{
std::condition_variable cvRunOver;
std::mutex mtxRunOver;
std::unique_lock <std::mutex> ulkRunOver(mtxRunOver);
QString workerThreadRes;
std::thread workThread([&]()
{
workThread.detach();
do_some_process_for_seconds();
cvRunOver.notify_all();
LOG(INFO)<<"to leave the subthread";
google::FlushLogFiles(google::GLOG_INFO);
return;
});
while (cvRunOver.wait_for(ulkRunOver, std::chrono::milliseconds(100)) == std::cv_status::timeout)
{
qApp->processEvents();
auto curTim = std::chrono::steady_clock::now();
std::chrono::duration<float> escapedTim= curTim-lastTim;
if(std::chrono::duration_cast<std::chrono::seconds>(escapedTim).count()>=5)
{
LOG(INFO) << "processEvents()";
google::FlushLogFiles(google::GLOG_INFO);
lastTim = curTim;
}
}
LOG(INFO) << "get lock and continue to run";
google::FlushLogFiles(google::GLOG_INFO);
}
Run Code Online (Sandbox Code Playgroud)
以下是程序无法正常工作时的相关日志:
Log line format: [IWEF]hh:mm:ss.uuuuuu threadid file:line] …Run Code Online (Sandbox Code Playgroud) 我正在使用std::condition_variable::wait_untilC++ 进行工作,并且正在使用std::chrono::system_clock和std::chrono::steady_clock来管理等待时间。阅读文档后,我明白使用时睡眠时间不应受到系统时间变化的影响std::chrono::steady_clock,而使用时可能会改变std::chrono::system_clock。
但是,我的代码的行为不同:对于两种时钟类型,等待时间均受系统时间的影响。这是一个最小的可重现示例:
#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>
#include <ctime>
#include <sys/time.h>
#include <condition_variable>
#include <atomic>
std::atomic<bool> flag = false;
std::condition_variable cv;
void wait_using_system_clock()
{
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
std::mutex mtx;
std::unique_lock lock(mtx);
cv.wait_until(lock, std::chrono::system_clock::now() + std::chrono::seconds(20), [](){return flag.load();});
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::cout << "Time difference [using system clock] = " << std::chrono::duration_cast<std::chrono::seconds>(end - begin).count() << "s" << std::endl;
}
void wait_using_steady_clock()
{
std::chrono::steady_clock::time_point begin = …Run Code Online (Sandbox Code Playgroud)