了解Volatile.Read/Write

No *_*ame 12 c# volatile thread-synchronization

我正在尝试理解C#Volatile类.

正如我读到的:

  • Volatile.Write方法强制将位置中的值写入调用点.此外,任何早期的程序订单加载和存储必须在调用Volatile.Write之前发生.

  • Volatile.Read方法强制在呼叫点读取位置中的值.此外,任何后续的程序订单加载和存储必须在调用Volatile.Read之后发生.

这是否意味着:

internal sealed class ThreadsSharingData {    
    private Int32 m_flag = 0;
    private Int32 m_value = 0;
    // This method is executed by one thread
    public void Thread1() {        
        // Note: 5 must be written to m_value before 1 is written to m_flag
        m_value = 5;
        Volatile.Write(ref m_flag, 1);        
    }

    // This method is executed by another thread
    public void Thread2() {        
        // Note: m_value must be read after m_flag is read
        if (Volatile.Read(ref m_flag) == 1)
        Console.WriteLine(m_value);        
    }    
}
Run Code Online (Sandbox Code Playgroud)

Volatile.Write(ref m_flag, 1);在开始写入之前,cpu会等待命令m_flag吗?

这有助于线程同步?

dca*_*tro 7

cpu将在Volatile.Write之前等待命令(ref m_flag,1); 在开始写入m_flag之前?

Eeeh,有点儿.一个更好的方法是:它保证,如果任何其他线程看到m_flag设置为1,它们也会看到m_value设置为5.

这有助于线程同步?

我不会说它有助于同步 - 但它确实有助于实现正确性.

如果您没有使用易失性读/写,则编译器/运行时/ cpu可能会重新排序方法中的两条指令Thread1,并且程序可以打印0,5或根本不打印.

使用易失性读/写,程序将打印5或根本不打印,但从打印0.这是预期的行为.


das*_*ght 5

这对线程同步有何帮助?

从设置命令执行顺序的意义上来说,它无助于线程同步。它可以让您确保并发线程以特定顺序观察内存中值的更改(在特定顺序对于程序逻辑很重要的情况下)。

Volatile.Write(ref m_flag, 1);[] CPU在开始写入之前是否等待命令m_flag

不,要写入的命令m_value已经执行。但是,其结果在 CPU 核心之外可能不可见 - 特别是,在不同核心上运行的线程可能会在写入它的命令完成执行m_value 后读取旧值。5这是因为新值可能在CPU的缓存中,而不是在内存中。

如果你写

m_value = 5;
m_flag = 1;
Run Code Online (Sandbox Code Playgroud)

Volatile.Write(ref m_flag, 1)另一个核心可能会以不同的顺序看到写入:首先它会看到成为m_flag1然后它会看到m_value成为5。如果您的其他线程使用 的值m_flag来判断 的有效性m_value,则逻辑可能会被破坏:例如,Thread2可能偶尔会打印零。