我試圖停止多個工作線程使用std::atomic_flag
。從Issue using std::atomic_flag with worker thread開始了以下工作:std :: atomic_flag停止多個線程
#include <iostream>
#include <atomic>
#include <chrono>
#include <thread>
std::atomic_flag continueFlag;
std::thread t;
void work()
{
while (continueFlag.test_and_set(std::memory_order_relaxed)) {
std::cout << "work ";
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void start()
{
continueFlag.test_and_set(std::memory_order_relaxed);
t = std::thread(&work);
}
void stop()
{
continueFlag.clear(std::memory_order_relaxed);
t.join();
}
int main()
{
std::cout << "Start" << std::endl;
start();
std::this_thread::sleep_for(std::chrono::milliseconds(200));
std::cout << "Stop" << std::endl;
stop();
std::cout << "Stopped." << std::endl;
return 0;
}
試圖改寫成多個工作線程:
#include <iostream>
#include <atomic>
#include <chrono>
#include <thread>
#include <vector>
#include <memory>
struct thread_data {
std::atomic_flag continueFlag;
std::thread thread;
};
std::vector<thread_data> threads;
void work(int threadNum, std::atomic_flag &continueFlag)
{
while (continueFlag.test_and_set(std::memory_order_relaxed)) {
std::cout << "work" << threadNum << " ";
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void start()
{
const unsigned int numThreads = 2;
for (int i = 0; i < numThreads; i++) {
////////////////////////////////////////////////////////////////////
//PROBLEM SECTOR
////////////////////////////////////////////////////////////////////
thread_data td;
td.continueFlag.test_and_set(std::memory_order_relaxed);
td.thread = std::thread(&work, i, td.continueFlag);
threads.push_back(std::move(td));
////////////////////////////////////////////////////////////////////
//PROBLEM SECTOR
////////////////////////////////////////////////////////////////////
}
}
void stop()
{
//Flag stop
for (auto &data : threads) {
data.continueFlag.clear(std::memory_order_relaxed);
}
//Join
for (auto &data : threads) {
data.thread.join();
}
threads.clear();
}
int main()
{
std::cout << "Start" << std::endl;
start();
std::this_thread::sleep_for(std::chrono::milliseconds(200));
std::cout << "Stop" << std::endl;
stop();
std::cout << "Stopped." << std::endl;
return 0;
}
我的問題是「問題部門」上面。即創建線程。我無法圍繞如何實例化線程並將變量傳遞給工作線程。
現在的錯誤是引用此行threads.push_back(std::move(td));
,錯誤號爲Error C2280 'thread_data::thread_data(const thread_data &)': attempting to reference a deleted function
。
嘗試使用的unique_ptr這樣的:
auto td = std::make_unique<thread_data>();
td->continueFlag.test_and_set(std::memory_order_relaxed);
td->thread = std::thread(&work, i, td->continueFlag);
threads.push_back(std::move(td));
在行td->thread = std::thread(&work, i, td->continueFlag);
給出錯誤std::atomic_flag::atomic_flag(const std::atomic_flag &)': attempting to reference a deleted function
。我從根本上誤解了std :: atomic_flag的使用嗎?它確實既不可移動也不可複製?
我沒有閱讀代碼,所以這可能不適用。但'std :: atomic_flag'是相當低的水平,使用起來有點棘手。在我看來,'std :: atomic'在這裏更合適。它看起來就像普通的'bool':'if(my_flag)...'和'my_flag = true;'和'my_flag = false;'。 –
根據標準'std :: atomic_flag'保證是無鎖的。一個簡單的工作線程測試增加一個由'while(continueFlag)'std :: atomic_flag包裹的計數器比'std :: atomic'快100%以上。鑑於這是一個綜合性的例子,它仍然表明,如果您經常對旗幟進行輪詢,旗標版本會更好。我傾向於在半關鍵部分進行民意調查,以瞭解工作是否被取消。 –
Sheph
除非你是一個非常時髦的系統'std :: atomic'將被鎖定。我非常懷疑那個和'std :: atomic_flag'之間的實際速度差別會很明顯。如果您的應用程序的性能受檢查原子變量的速度限制,那麼它沒有做任何實際工作,需要重新設計。 –