【发布时间】:2016-02-27 12:32:47
【问题描述】:
我正在尝试使用std::atomic_flag 停止多个工作线程。从Issue using std::atomic_flag with worker thread开始,以下作品:
#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>在这里更合适。它看起来就像一个普通的bool:if(my_flag) ...和my_flag = true;和my_flag = false;。 -
根据标准
std::atomic_flag保证无锁。一个简单的工作线程测试增加由while(continueFlag)包裹的计数器,std::atomic_flag比std::atomic<bool>快 100% 以上。鉴于这是一个综合示例,它仍然表明如果您经常轮询标志,标志版本会好得多。我倾向于在半关键部分进行投票,以了解工作是否被取消。 -
除非你在一些非常时髦的系统上
std::atomic<bool>将是无锁的。我非常怀疑它与std::atomic_flag之间的任何实际速度差异是否会很明显。如果您的应用程序的性能受到检查原子变量的速度的限制,那么它没有做任何实际工作,需要重新设计。
标签: c++ multithreading c++11 atomic