Gam*_*ads 6 c++ c++11 stdthread stdatomic
我std::thread在我的C++代码中使用一个不断轮询一些数据并将其添加到缓冲区.我使用a C++ lambda来启动这样的线程:
StartMyThread() {
thread_running = true;
the_thread = std::thread { [this] {
while(thread_running) {
GetData();
}
}};
}
Run Code Online (Sandbox Code Playgroud)
thread_running 是atomic<bool>在类头中声明的.这是我的GetData功能:
GetData() {
//Some heavy logic
}
Run Code Online (Sandbox Code Playgroud)
接下来我还有一个StopMyThread函数,我将其设置thread_running为false,以便它退出while中的while循环lambda block.
StopMyThread() {
thread_running = false;
the_thread.join();
}
Run Code Online (Sandbox Code Playgroud)
据我了解,我可以暂停和使用恢复该线程std::condition_variable的指出这里在我前面的问题.
但是,如果我只是使用std::atomic<bool> thread_running执行或不执行GetData()下面的逻辑,是否有缺点?
GetData() {
if (thread_running == false)
return;
//Some heavy logic
}
Run Code Online (Sandbox Code Playgroud)
与使用std::condition_variable 此处 描述的方法相比,这会消耗更多的CPU周期吗?
当您想要有条件地停止另一个线程时,条件变量非常有用。因此,您可能有一个始终运行的“工作”线程,当它发现与运行无关时,它会等待。
原子解决方案要求您的 UI 交互与工作线程同步,或者需要非常复杂的逻辑来异步执行。
作为一般规则,您的 UI 响应线程不应在工作线程的非就绪状态时阻塞。
struct worker_thread {
worker_thread( std::function<void()> t, bool play = true ):
task(std::move(t)),
execute(play)
{
thread = std::async( std::launch::async, [this]{
work();
});
}
// move is not safe. If you need this movable,
// use unique_ptr<worker_thread>.
worker_thread(worker_thread&& )=delete;
~worker_thread() {
if (!exit) finalize();
wait();
}
void finalize() {
auto l = lock();
exit = true;
cv.notify_one();
}
void pause() {
auto l = lock();
execute = false;
}
void play() {
auto l = lock();
execute = true;
cv.notify_one();
}
void wait() {
Assert(exit);
if (thread)
thread.get();
}
private:
void work() {
while(true) {
bool done = false;
{
auto l = lock();
cv.wait( l, [&]{
return exit || execute;
});
done = exit; // have lock here
}
if (done) break;
task();
}
}
std::unique_lock<std::mutex> lock() {
return std::unique_lock<std::mutex>(m);
}
std::mutex m;
std::condition_variable cv;
bool exit = false;
bool execute = true;
std::function<void()> task;
std::future<void> thread;
};
Run Code Online (Sandbox Code Playgroud)
或类似的东西。
它拥有一个线程。只要线程处于play()模式,就会重复运行任务。如果pause()下次task()完成,工作线程将停止。如果您在通话结束play()之前task(),它不会注意到pause().
唯一的等待是在 的销毁worker_thread时,它会自动通知工作线程它应该退出并等待它完成。
您可以手动.wait()或.finalize()也可以。 .finalize()是异步的,但如果您的应用程序正在关闭,您可以尽早调用它,并给工作线程更多的时间来清理,同时主线程会清理其他地方的东西。
.finalize()无法逆转。
代码未测试。