我是
std::thread
的新手。我需要从另一个线程让 std::thread
进入睡眠状态,这可能吗?在示例中,我看到的只是类似的代码:
std::this_thread::sleep_for(std::chrono::seconds(1));
但我想做的是:
std::thread t([]{...});
t.sleep(std::chrono::seconds(1));
或者
sleep(t, std::chrono::seconds(1));
有什么想法吗?
因为
sleep_for
是同步的,所以它只在当前线程中才真正有意义。您想要的是一种挂起/恢复其他线程的方法。该标准没有提供执行此操作的方法(据我所知),但您可以使用依赖于平台的方法,使用 native_handle
。
例如在 Windows 上,
SuspendThread
和 ResumeThread
。
但更重要的是,几乎从来没有必要这样做。通常,当您遇到标准未提供的基本需求时,这是一个危险信号,表明您正在走上一条危险的设计道路。考虑以不同的方式实现更大的目标。
不。该标准没有给你这样的便利,也不应该。睡眠有什么作用?它将给定线程的执行暂停至少给定的时间。其他线程是否可以在不同步的情况下知道给定线程可以进入睡眠状态以获得更好的性能?
不。您必须提供一个同步接口,这将抵消线程的性能增益。唯一拥有是否可以休眠所需信息的线程是线程本身。因此
std::thread
没有成员 sleep
,而 std::this_thread
有一个成员。
要控制自定义线程执行,类似的方法是有效的:
#include <atomic>
#include <thread>
#include <iostream>
#include <condition_variable>
class WorkerControl
{
public:
void Suspend()
{
sleep_ = true;
};
void Resume()
{
sleep_ = false;
cv_.notify_one();
};
void Exit()
{
exit_ = true;
};
std::atomic_bool sleep_{ false };
std::condition_variable cv_{};
std::atomic_bool exit_{ false };
std::mutex mutex_{};
};
void Worker(WorkerControl& control)
{
std::unique_lock lk(control.mutex_);
while (!control.exit_.load()) {
if (!control.sleep_.load()) {
std::cout << ".";
std::this_thread::sleep_for(std::chrono::milliseconds(500)); // (Some work to do)
}
else {
std::cout << "\n" << "enters sleep" << "\n";
control.cv_.wait(lk, [&control]() { return control.sleep_.load() == false; });
std::cout << "wakes up" << "\n";
}
}
std::cout << "\n" << "exits" << "\n";
}
int main()
{
WorkerControl control{};
std::thread tr(Worker, std::ref(control));
// For example:
std::this_thread::sleep_for(std::chrono::seconds(5)); // (Do something 5 seconds)
control.Suspend();
std::this_thread::sleep_for(std::chrono::seconds(3)); // (Do something 3 seconds)
control.Resume();
std::this_thread::sleep_for(std::chrono::seconds(10)); // (Do something 10 seconds)
control.Suspend();
std::this_thread::sleep_for(std::chrono::seconds(3)); // (Do something 3 seconds)
control.Resume();
std::this_thread::sleep_for(std::chrono::seconds(5)); // (Do something 5 seconds)
control.Exit();
tr.join();
}
输出:
..........
suspended
resumed
....................
suspended
resumed
..........
exited