yek*_*chi 3 c++ multithreading producer-consumer stdatomic
原始问题:
我得到了一个结构数组,并在主线程中读取它时将其填充到一个单独的线程中:
struct DataModel MyData[1024];
struct DataModel
{
bool IsFilled;
float a;
float b;
}
Run Code Online (Sandbox Code Playgroud)
我有一个Thread,它将Mydata数组从0索引填充到最后一个索引(在上面是1024).
然后我从填充线程中获取最后一个填充的结构索引.
然后我尝试读取元素的值,其中一个索引低于填充的索引.
我们假设当第500个元素被填充时,我从MyData数组的499元素中读取值,所以我确保我没有读取正在写入的数组元素.
Q1:这个线程安全吗?
Q2:是否有可能发生未定义的行为或误读vales?
进一步编辑:
问题是编辑不当以添加更多细节,这就是为什么它引入了不一致的答案,所以我分开了以前的编辑,以提高答案和接受答案的一致性.
编辑1:这是可能实施的建议.虽然它可能显示错误的结果,但只是我想询问线程安全和未定义的行为,以下解决方案可能会显示各种结果,但我试图首先询问线程安全性.
std::atomic<int> FilledIndex;
void FillingMyData(struct DataModel myData[])
{
for(size_t i = 0; i < 1024; i++)
{
myData[i].a = rand();
myData[i].b = rand();
myData[i].IsFilled = true;
FilledIndex = i;
}
}
int main()
{
std::thread ReadThread(FillingMyData, MyData);
while(FilledIndex < 1024)
{
std::cout << MyData[FilledIndex].a;
}
ReadThread.join();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
是的,可以安全地处理同一阵列中的单独对象.即使数组是一个对象,它也是我们正在处理的数组元素,它们是单独的对象.只要您没有读取编写器正在写入的元素,就没有数据争用,并且代码已定义了行为.您的已发布代码确实存在同步问题,但此处的其他答案涵盖了这些问题.
这里可能发生的是所谓的虚假共享.在这些情况下会发生的情况是,单独的对象位于内存中的同一缓存行中.当核心/线程更改一个对象时,该缓存行被标记为已更改.这意味着另一个核心/线程必须重新同步该行以引入任何更改,这意味着两个核心/线程不能同时运行.这只是性能损失,程序仍会给出正确的结果,它会慢一点.