了解Volatile.Read/Write

时间:2014-06-19 12:52: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);        
    }    
}

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

这有助于线程同步吗?

2 个答案:

答案 0 :(得分:6)

  

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

Eeeh,有点儿。更好的说法是:保证,如果任何其他线程将m_flag设置为1,他们也会将m_value设置为5。

  

这有助于线程同步吗?

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

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

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

答案 1 :(得分:3)

  

这对线程同步有何帮助?

在设置命令执行顺序的意义上,它无助于线程同步。它允许您确保并发线程以特定顺序观察内存中值的更改,以防特定顺序对程序逻辑很重要。

  

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

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

如果你写

5

而不是m_value = 5; m_flag = 1; 其他核心可能会以不同的顺序看到写入:首先它会看到Volatile.Write(ref m_flag, 1)变为m_flag,之后会看到1 }成了m_value。如果您的其他主题使用5的值来判断m_flag的有效性,则逻辑可能会被破坏:例如,m_value可能偶尔会打印零。