如果我们在 C# 中有以下代码:

int a = 0;
int b = 0;

void A() // runs in thread A
{
    a = 1;
    Thread.MemoryBarrier();
    Console.WriteLine(b);
}

void B() // runs in thread B
{
    b = 1;
    Thread.MemoryBarrier();
    Console.WriteLine(a);
}
MemoryBarriers 确保写指令发生在读之前。但是,是否可以保证一个线程的写入被另一个线程的读取看到?换句话说,是否保证至少一个线程打印 1 或两个线程都可以打印 0

我知道已经存在几个与 C# 中的“新鲜度”和 MemoryBarrier 相关的问题,例如 thisthis 。然而,它们中的大多数处理写-释放和读-获取模式。在这个问题中发布的代码非常具体地说明了在指令按顺序排列的情况下,是否保证读取可以查看写入。

最佳答案

不能保证看到两个线程都写入 1It only guarantees the order of read/write operations 基于此规则:



所以这基本上意味着 thread A 的线程不会在 屏障调用之前使用变量 b 读取 的值。但如果您的代码是这样的,它仍然会缓存该值:

void A() // runs in thread A
{
    a = 1;
    Thread.MemoryBarrier();
    // b may be cached here
    // some work here
    // b is changed by other thread
    // old value of b is being written
    Console.WriteLine(b);
}

并行执行的竞争条件错误非常难以重现,因此我无法为您提供肯定会执行上述场景的代码,但我建议您将 volatile keyword 用于不同线程使用的变量,因为它完全按照您的意愿工作 - 让您重新阅读变量:
volatile int a = 0;
volatile int b = 0;

void A() // runs in thread A
{
    a = 1;
    Thread.MemoryBarrier();
    Console.WriteLine(b);
}

void B() // runs in thread B
{
    b = 1;
    Thread.MemoryBarrier();
    Console.WriteLine(a);
}

关于c# - 内存屏障是否保证在 C# 中重新读取?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38050681/

10-16 19:07