Multithreading 内存排序、脱离其他执行和多线程安全

Multithreading 内存排序、脱离其他执行和多线程安全,multithreading,memory,strict-weak-ordering,Multithreading,Memory,Strict Weak Ordering,最近我一直在读关于记忆重新排序的文章。我的问题是关于多线程场景的。考虑下面的例子: A = 0; B = 0; Thread 1 on Processor 1 Thread 2 on Processor 2 A = 100; while(B== 0); B = 1; //access

最近我一直在读关于记忆重新排序的文章。我的问题是关于多线程场景的。考虑下面的例子:

A = 0;
B = 0;

Thread 1 on Processor 1                       Thread 2 on Processor 2

    A = 100;                                      while(B== 0);
    B = 1;                                       //access A here
我一直在X86-64 windows平台上编写代码,从未考虑到A和B的存储可以重新排序(在编译器级别或硬件级别),我可能会在线程2中以B=0结束,并发现A仍然是0。这样的代码从来没有遇到过任何问题或讨厌的bug。这是因为x86-x64是强顺序的,windows C编译器也是如此

对于要在任何其他具有弱有序内存的平台上执行的代码,我是否需要确保更新并访问锁中的a和B(假设底层锁实现使用内存屏障,并确保只有在所有处理器内核中都可以看到之前的加载和存储之后才释放锁)

谢谢

这是因为x86-x64是强顺序的,windows C编译器也是如此

实际上,
X86
是一个强顺序CPU,不允许存储重新排序。因此,所有CPU内核都将遵守编译器发出的顺序

但是,
B
在处理器1上修改,而在处理器2上读取。这是不允许的C内存模型没有同步(尝试最大限度的编译器优化,它可能会停止工作)

虽然可以使用锁定在核心之间进行同步,但这可能会有问题,因为您正在
B
上旋转。如果在获取锁时发生这种情况,处理器1无法更新该值


正确的解决方案是使
B
原子化。这将保证所有级别上的正确排序。

LMimsey您的意思是最大限度地优化可以启用编译器级别的重新排序。我没有得到“这在C内存模型中是不允许的”。强序x86应该保证当B=1时A=100,这就是上面的示例想要得到的。另外,我的问题的下一部分,在一个具有弱序内存的平台上,我是否需要注意更新锁中的A和B。所有操作系统平台上的Do lock primitives在锁释放逻辑中内部插入内存屏障,因为否则即使锁定也可能无法防止硬件内存访问重新排序。2个或更多线程对单个内存位置的读/写访问违反内存模型规则(也称为数据竞争)。结果是未定义的行为。例如,由于编译器可能不希望在Core2上更新
B
,因此它可能只是将其从循环中删除。循环将永远不会退出。如果
B
是原子的(C11 atomics库),那么即使在最脆弱的平台上,它也保证工作。编译器将插入必要的内存屏障。