我正在对C ++原子进行一种练习。
我编写了以下代码,其中我启动了2个读取器线程,这些读取器线程基于就绪计数器读取一些结构化数据,每次更新数据时主计数器都会增加2。每个读取器线程一旦标志为非零读取数据并将计数器递减1。 代码
#include <atomic>
#include <thread>
#include <iostream>
#include <functional>
#include <chrono>
struct Foo
{
int a;
int b;
int c;
};
int main()
{
unsigned long writeCnt { 0 };
std::atomic<int> dataReady {0};
//Shared data
Foo data {0, 0, 0};
//Readers accumulate data here
Foo dataBuf[2][1000];
//Reader threads
std::thread threads[2];
//A pointer to a buffer assigned to a reader
Foo (*curBuf)[1000] = dataBuf;
//Thread's ID
int threadNum { 0 };
//Starting readers
for (auto & item : threads)
{
item = std::thread(std::bind([&dataReady,&data](Foo * buf, const int threadNum)
{
unsigned long readCnt { 0 };
while (readCnt < 1000)
{
auto ready = dataReady.load(std::memory_order_relaxed);
std::cout << "Thread #" << threadNum << " ready " << ready << " read cnt " << readCnt <<std::endl;
if(ready > 0)
{
std::atomic_thread_fence(std::memory_order_acquire);
buf[readCnt].a = data.a;
buf[readCnt].b = data.b;
buf[readCnt].c = data.c;
std::atomic_thread_fence(std::memory_order_release);
dataReady.store(ready - 1, std::memory_order_relaxed);
++readCnt;
}
else
{
continue;
}
}
},*(curBuf++),threadNum++));
}
//Writer loop
while (writeCnt < 1000)
{
auto ready = dataReady.load(std::memory_order_relaxed);
std::cout << "Main thread ready " << ready << " write cnt " << writeCnt << std::endl;
if(ready == 0)
{
std::atomic_thread_fence(std::memory_order_acquire);
data.a = writeCnt;
data.b = writeCnt;
data.c = writeCnt;
std::atomic_thread_fence(std::memory_order_release);
dataReady.store(2, std::memory_order_relaxed);
++writeCnt;
}
else
{
continue;
}
}
//Joining readers
for(auto & item : threads)
{
if(item.joinable())
{
item.join();
}
}
//Print accumulated data
for(const auto & buffer : dataBuf)
{
for(const auto & item : buffer)
{
std::cout << item.a << " " << item.b << " " << item.c << std::endl;
}
}
}
现在,只有一个线程可以双读更新的数据并不重要。当读者完成阅读时,我担心writeCnt
会在730左右停止。
这是由内存重新排序引起的不当行为以及为什么添加了线程围栏?
我在这里缺少什么?