[英]Stop infinite looping thread from main
我对线程还比较陌生,但我仍在学习最佳技术和C ++ 11线程库。 现在,我正在实现一个无限循环的工作线程,执行一些工作。 理想情况下,主线程可能会不时地停止循环,以与工作线程正在生成的信息进行同步,然后再次启动它。 我最初的想法是这样的:
// Code run by worker thread
void thread() {
while(run_) {
// Do lots of work
}
}
// Code run by main thread
void start() {
if ( run_ ) return;
run_ = true;
// Start thread
}
void stop() {
if ( !run_ ) return;
run_ = false;
// Join thread
}
// Somewhere else
volatile bool run_ = false;
我对此并不完全确定,因此我开始进行研究,结果发现,实际上同步并不是必需使用volatile,实际上它通常是有害的。 另外,我发现了这个答案 ,它描述的过程几乎与我所描述的过程相同。 但是,在答案的评论中,此解决方案被描述为无效的,因为volatile不能保证不同的处理器内核能够轻松地(如果有的话)传达volatile值的变化。
我的问题是:我应该使用原子标志还是完全使用其他标志? 究竟什么是缺少挥发物的属性,然后通过有效解决我的问题所需的任何构造提供了该属性?
您是否正在寻找Mutex? 它们被制成为锁定线程,以避免共享数据上的冲突。 您在找什么吗?
我认为您想使用std :: mutex使用屏障同步 ?
还可以看一下boost线程 ,以获得相对高级的线程库
从链接中查看以下代码示例:
#include <iostream>
#include <map>
#include <string>
#include <chrono>
#include <thread>
#include <mutex>
std::map<std::string, std::string> g_pages;
std::mutex g_pages_mutex;
void save_page(const std::string &url)
{
// simulate a long page fetch
std::this_thread::sleep_for(std::chrono::seconds(2));
std::string result = "fake content";
g_pages_mutex.lock();
g_pages[url] = result;
g_pages_mutex.unlock();
}
int main()
{
std::thread t1(save_page, "http://foo");
std::thread t2(save_page, "http://bar");
t1.join();
t2.join();
g_pages_mutex.lock(); // not necessary as the threads are joined, but good style
for (const auto &pair : g_pages) {
std::cout << pair.first << " => " << pair.second << '\n';
}
g_pages_mutex.unlock();
}
我建议使用std::mutex
和std::condition_variable
解决问题。 这是一个示例如何与C ++ 11一起工作的:
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
int main()
{
mutex m;
condition_variable cv;
// Tells, if the worker should stop its work
bool done = false;
// Zero means, it can be filled by the worker thread.
// Non-zero means, it can be consumed by the main thread.
int result = 0;
// run worker thread
auto t = thread{ [&]{
auto bound = 1000;
for (;;) // ever
{
auto sum = 0;
for ( auto i = 0; i != bound; ++i )
sum += i;
++bound;
auto lock = unique_lock<mutex>( m );
// wait until we can safely write the result
cv.wait( lock, [&]{ return result == 0; });
// write the result
result = sum;
// wake up the consuming thread
cv.notify_one();
// exit the loop, if flag is set. This must be
// done with mutex protection. Hence this is not
// in the for-condition expression.
if ( done )
break;
}
} };
// the main threads loop
for ( auto i = 0; i != 20; ++i )
{
auto r = 0;
{
// lock the mutex
auto lock = unique_lock<mutex>( m );
// wait until we can safely read the result
cv.wait( lock, [&]{ return result != 0; } );
// read the result
r = result;
// set result to zero so the worker can
// continue to produce new results.
result = 0;
// wake up the producer
cv.notify_one();
// the lock is released here (the end of the scope)
}
// do time consuming io at the side.
cout << r << endl;
}
// tell the worker to stop
{
auto lock = unique_lock<mutex>( m );
result = 0;
done = true;
// again the lock is released here
}
// wait for the worker to finish.
t.join();
cout << "Finished." << endl;
}
通过本质上实现自旋锁,您可以对std::atomic
进行相同的操作。 自旋锁的速度可能比互斥锁慢。 因此,我在boost网站上重复了建议:
我相信互斥量和条件变量是解决您的问题的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.