如何在一个睡眠状态的std::thread中唤醒它
在本文中,我们将讨论如何在一个睡眠状态的 std::thread 中唤醒它。众所周知,当一个线程处于睡眠状态时,它不能退出。因此它使用以下命令被唤醒:
std::condition_variable
以下是实现同样功能的伪代码:
// 自定义类
struct MyClass {
// 构造函数
MyClass()
: my_thread([this]() {
this->thread();
})
{
}
// 析构函数
~MyClass()
{
{
std::lock_guard<std::mutex> l(m_);
stop_ = true;
}
c_.notify_one();
my_thread.join();
}
// 实现线程的函数
void thread()
{
while (this->wait_for(std::chrono::minutes(2)))
SendStatusInfo(some_info);
}
// 当线程停止时返回false的函数
template <class Duration>
bool wait_for(Duration duration)
{
std::unique_lock<std::mutex> l(m_);
return !c_.wait_for(l, duration, [this]() {
return stop_;
});
}
// 条件变量
std::condition_variable c_;
std::mutex m_;
bool stop_ = false;
std::thread my_thread;
};
C++
以下是另一个示例,以说明相同的方法:
std::promise/std::future
上述命令可以用作更简单的替代方法。在这种情况下,一个 Future 不易受到错误唤醒,也不需要一个 mutex 进行同步。以下是实现同样功能的伪代码:
// Promise Condition
std::promise<void> pr;
// 开始线程
std::thread thr{
[fut = pr.get_future()]{
// 反复迭代直到条件退出
while (true){
if (fut.wait_for(std::chrono::minutes(2))
!= std::future_status::timeout) return;
}
}
}
;
// 准备停止
pr.set_value();
// 加入线程
thr.join();
C++
以下是用于说明上述概念的程序:
// C++程序,演示线程在睡眠时被唤醒
#include <bits/stdc++.h>
using namespace std;
std::deque<int> q;
std::mutex mu;
std::condition_variable cond;
// 创建线程1的函数
void function_1()
{
// 初始化计数器变量
int count = 10;
// 执行到计数器变量为正
while (count > 0) {
// 互斥锁
std::unique_lock<mutex> locker(mu);
// 将当前的计数器变量推入到队列中
q.push_front(count);
locker.unlock();
cond.notify_one();
// 如果有线程在等待,则通知该线程
std::this_thread::sleep_for(
chrono::seconds(1));
// 减小计数器变量
count--;
}
}
// 创建线程2的函数
void function_2()
{
// 初始化一个变量以从队列中获取数据
int data = 0;
while (data != 1) {
std::unique_lock<mutex> locker(mu);
cond.wait(locker, []() {
return !q.empty();
});
// 睡眠结束后虚假唤醒
data = q.back();
q.pop_back();
locker.unlock();
// 输出信息
cout << "t2 got a value from"
" t1"
<< data << '\n';
}
}
// 主函数
int main()
{
// 创建线程1
std::thread t1(function_1);
// 创建线程2
std::thread t2(function_2);
// 等待线程结束
t1.join();
t2.join();
return 0;
}
C++
输出结果: