多线程环境中初始化的内存语义(C++)
问题描述:
我不确定C++初始化过程的内存语义。 假设我们有以下程序。多线程环境中初始化的内存语义(C++)
#include <iostream>
#include <thread>
using namespace std;
void func(int* arr, int s)
{
for (int i = 0; i < s; ++i)
{
cout << arr[i] << endl;
}
}
int main(int argc, char *argv[])
{
int *a = new int[10];
for (int i = 0; i < 10; ++i)
{
a[i] = i;
}
// Do I need some sort of memory barrier here?
std::thread t(func, a, 10);
t.join();
return 0;
}
新线程是否会看到一个数组已正确初始化?或者我需要在两者之间插入某种内存屏障。 C++语言如何定义初始化的内存语义?
我担心的是,所有的写入到阵列一个[10]可以坐在一个CPU的写缓冲,我们开始一个新的线程在不同的CPU,这可能不遵守初始化写道。
我们是否需要内存围栏进行初始化,以便能够通过运行在不同的cpus上的后续发布的线程来观察?
答
在执行线程构造函数之前父项中的操作与子项中运行的线程过程之间存在“发生前 - 之间”关系。特别是标准说(f
是线程程序):
同步:构造函数的调用的完成与
f
副本的调用开始同步。
这部分被发现[thread.thread.constr]
谢谢你的理由。我很难阅读标准。我找到你的报价。通过“与...同步”,我想这意味着编译器可能会在调用f副本之前插入fence以确保在调用f之前所有存储都将被观察到? –
@OliverYoung:该标准没有提及内存隔离,因为并非所有的CPU架构都需要它们。该标准说明了编译器需要确保副作用可见的地方,以及操作重叠的位置(创建竞争条件),编译器负责使用任何CPU功能提供的指定行为。 –
我明白了。只要非常清楚,初始化部分就会同步/“发生之前”调用f的副本。这意味着没有竞争条件,不需要同步操作,对吧? –