已知
A线程:设置a,再设置pA = &a
B线程:等待pA有效后,再对* pA访问
在x86下可以保证B线程取得a的最新值,但其他更弱一致性的cpu(arm,powerpc)无这种保证,几乎是会出错的。
上面还是比较容易理解的
但是如果延伸一步:
A线程:pA = new {5}
B线程:等待pA有效后,再对*pA访问
在弱一致性cpu上是否能保证正确呢?对pA的赋值是否应当使用atomic的release语义呢……
主要是不明白c++标准是否已经要求弱一致性cpu上new操作有无自带release语义。为了安全似乎是要加了比较放心。没有开发环境希望有人帮测
两线程
#include <iostream>
#include <type_traits>
#include <thread>
#include <assert.h>
struct
{
int value = 0;
char _1[128];
int* p = NULL;
char _2[128];
volatile bool start = false;
char _3[128];
} s_context;
#define TEST_NEW 1
int main()
{
int* alloced[4] = {};
std::thread A([&alloced]
{
while (!s_context.start) // 等待start
;
#if TEST_NEW == 1
s_context.p = new int{ 5 }; // 在B申请并归还的地址上,重新申请并赋值5
#else
s_context.value = 5;
s_context.p = &s_context.value;
#endif
printf("A End\n");
});
std::thread B([&alloced]
{
#if TEST_NEW == 1
//在某个new的位置赋值3,并立刻归还内存,使得此内存位于B的cache之中
alloced[0] = new int{ 3 };
delete alloced[0];
#else
s_context.value = 3; //在A的工作开始之前,令int value = 3
#endif
while (!s_context.start) //等待start
;
while ((int* volatile&)s_context.p == NULL)
;
int* pp = (int* volatile&)s_context.p;
if (*pp != 5)
{
puts("error!");
}
#if TEST_NEW == 1
printf("first allocated %p, second allocated %p, %s\n", alloced[0], pp,
alloced[0] == pp ? "same address" : "different address");
#endif
printf("B End\n");
});
std::this_thread::sleep_for(std::chrono::milliseconds(300));
// value应该被B赋值为3了
s_context.start = true; //令A、B开始
A.join();
B.join();
// printf("%p\n", alloced[0]);
return 0;
}