std::thread 可中断睡眠
Interruptible sleep in std::thread
我有一个简单的 C++11 线程程序,如下所示。
代码:
#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
int main(int argc, char *argv[]) {
std::cout << "My program starts" << std::endl;
std::atomic<bool> exit_thread(false);
std::thread my_thread = std::thread([&exit_thread]{
do {
std::cout << "Thread is doing something..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(5));
} while (!exit_thread);
});
std::this_thread::sleep_for(std::chrono::seconds(12));
exit_thread = true;
std::cout << "Might have to wait to exit thread" << std::endl;
my_thread.join();
return 0;
}
正如您在上面看到的,有一个循环,其中有一个 sleep_for
,它使线程休眠 5 秒,然后唤醒并再次循环,前提是 exit_thread
设置为 false。主线程等待 12 秒并准备通过将 exit_thread
设置为 true 首先退出,然后在线程上执行 join
。到现在都还好。
问题:
以上没问题,适用于 objective。 但是有一个"potential problem"。如果线程刚刚开始休眠,那么它需要 4 秒以上才能从休眠状态中发现它现在需要退出。这会延迟退出过程和销毁。
问题:
如何让线程以可中断的方式休眠?这样我就可以中断睡眠并立即退出线程,而不是通过取消睡眠而不是等待潜在的 4 或 3 或 2 秒。
我认为使用 std::condition_variable 可以解决这个问题?大概?我正在寻找一段代码来展示如何。
注意我的代码在 clang 和 gcc 上运行。
我们应该等待条件变量或信号量而不是休眠。这是执行此操作的最小更改:
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
int main()
{
std::cout << "My program starts" << std::endl;
std::atomic<bool> exit_thread(false);
std::condition_variable cv;
std::mutex m;
std::thread my_thread = std::thread([&exit_thread,&cv,&m]{
do {
std::cout << "Thread is doing something..." << std::endl;
{
std::unique_lock<std::mutex> lock(m);
cv.wait_for(lock, std::chrono::seconds(5));
}
} while (!exit_thread);
});
std::this_thread::sleep_for(std::chrono::seconds(12));
{
std::lock_guard<std::mutex> guard(m);
exit_thread = true;
}
cv.notify_all();
std::cout << "Thread stops immediately" << std::endl;
my_thread.join();
}
显然,我们确实需要互斥量:
Even if the shared variable is atomic, it must be modified under the
mutex in order to correctly publish the modification to the waiting
thread.
我有一个简单的 C++11 线程程序,如下所示。
代码:
#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
int main(int argc, char *argv[]) {
std::cout << "My program starts" << std::endl;
std::atomic<bool> exit_thread(false);
std::thread my_thread = std::thread([&exit_thread]{
do {
std::cout << "Thread is doing something..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(5));
} while (!exit_thread);
});
std::this_thread::sleep_for(std::chrono::seconds(12));
exit_thread = true;
std::cout << "Might have to wait to exit thread" << std::endl;
my_thread.join();
return 0;
}
正如您在上面看到的,有一个循环,其中有一个 sleep_for
,它使线程休眠 5 秒,然后唤醒并再次循环,前提是 exit_thread
设置为 false。主线程等待 12 秒并准备通过将 exit_thread
设置为 true 首先退出,然后在线程上执行 join
。到现在都还好。
问题:
以上没问题,适用于 objective。 但是有一个"potential problem"。如果线程刚刚开始休眠,那么它需要 4 秒以上才能从休眠状态中发现它现在需要退出。这会延迟退出过程和销毁。
问题:
如何让线程以可中断的方式休眠?这样我就可以中断睡眠并立即退出线程,而不是通过取消睡眠而不是等待潜在的 4 或 3 或 2 秒。
我认为使用 std::condition_variable 可以解决这个问题?大概?我正在寻找一段代码来展示如何。
注意我的代码在 clang 和 gcc 上运行。
我们应该等待条件变量或信号量而不是休眠。这是执行此操作的最小更改:
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
int main()
{
std::cout << "My program starts" << std::endl;
std::atomic<bool> exit_thread(false);
std::condition_variable cv;
std::mutex m;
std::thread my_thread = std::thread([&exit_thread,&cv,&m]{
do {
std::cout << "Thread is doing something..." << std::endl;
{
std::unique_lock<std::mutex> lock(m);
cv.wait_for(lock, std::chrono::seconds(5));
}
} while (!exit_thread);
});
std::this_thread::sleep_for(std::chrono::seconds(12));
{
std::lock_guard<std::mutex> guard(m);
exit_thread = true;
}
cv.notify_all();
std::cout << "Thread stops immediately" << std::endl;
my_thread.join();
}
显然,我们确实需要互斥量:
Even if the shared variable is atomic, it must be modified under the mutex in order to correctly publish the modification to the waiting thread.