[英]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.