我现在什么都不懂。考虑我有下一段代码(简化版):
#include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <chrono>
const auto k_sleep = std::chrono::seconds{3};
const auto k_wait = std::chrono::seconds{1};
const auto k_repeats = 20u;
void test()
{
std::mutex m;
std::condition_variable c;
bool processed = false;
std::thread worker{[&]() {
std::this_thread::sleep_for(k_sleep);
std::unique_lock<std::mutex> lock(m);
processed = true;
lock.unlock();
c.notify_one();
}};
std::unique_lock<std::mutex> lock(m);
if(c.wait_for(lock, k_wait, [&processed]() {
return processed;
}))
{
worker.join();
std::cout << "done" << std::endl;
}
else
{
worker.detach();
std::cout << "timeout" << std::endl;
}
}
int main()
{
for(auto i = 0u; i < k_repeats; ++i)
test();
}
几个问题:
condition_variable
(以及与thread
相关的所有其他内容)吗?timeout
?正如您所看到的,我正在运行线程并等待它(使用condition_variable
)一段时间。等待时间少于线程的执行时间。
使用VC ++(Visual Studio 2015,v 19.00.23026)和g ++(v 4.8.2),我打印了timeout
2次,然后我在调试器下卡住worker.join()
。如果我将k_sleep
增加到大的东西(相对于k_wait
而小循环计数),例如30秒 - 一切都会好的。
那么,为什么会这样呢?如果我做错了,请以正确的方式向我解释。感谢
答案 0 :(得分:0)
你的内存管理存在问题:
m
,c
和processed
)都在堆栈上分配,当您分离工作线程时,它们将超出范围。因此,当线程唤醒时,它将访问垃圾。因此,您需要在堆上分配数据,并确保不通过引用捕获变量。我总是希望将数据明确传递到std::thread
。
#include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <chrono>
#include <memory>
const auto k_sleep = std::chrono::seconds{ 3 };
const auto k_wait = std::chrono::seconds{ 1 };
const auto k_repeats = 20u;
struct Data
{
std::mutex m;
std::condition_variable c;
bool processed = false;
};
void test()
{
auto data = std::make_shared<Data>();
auto run = [](std::shared_ptr<Data> i_data) {
std::this_thread::sleep_for(k_sleep);
std::unique_lock<std::mutex> lock(i_data->m);
i_data->processed = true;
lock.unlock();
i_data->c.notify_one();
};
std::thread worker{ run, data };
std::unique_lock<std::mutex> lock(data->m);
if (data->c.wait_for(lock, k_wait, [&data]() {
return data->processed;
}))
{
worker.join();
std::cout << "done" << std::endl;
}
else
{
worker.detach();
std::cout << "timeout" << std::endl;
}
}
int main()
{
for (auto i = 0u; i < k_repeats; ++i)
test();
}