【问题标题】:understanding of Volatile.Read/Write对 Volatile.Read/Write 的理解
【发布时间】:2014-08-10 00:29:57
【问题描述】:

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

如我所见:

  • Volatile.Write 方法强制写入 location 中的值 到通话点。此外,任何早期的程序顺序 加载和存储必须在调用 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);        
    }    
}

cpu 会等待Volatile.Write(ref m_flag, 1); 之前的命令,然后再开始写入m_flag

这对线程同步有何帮助?

【问题讨论】:

  • 它仅与内存模型较弱的处理器相关,即获取和释放语义很重要的处理器。除了ARM内核之外,剩下的很少。它不是正确同步的替代品,编写没有同步的线程安全代码是一个非常先进的概念。否则,this question 已经很好地涵盖了。

标签: c# volatile thread-synchronization


【解决方案1】:

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

哎呀,有点。更好的表达方式是:可以保证,如果任何其他线程看到 m_flag 设置为 1,他们也会看到 m_value 设置为 5。

这对线程同步有何帮助?

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

如果您不使用 volatile 读取/写入,编译器/运行时/cpu 可能会重新排序 Thread1 方法中的两条指令,并且程序将能够打印 0、5 或什么都没有。

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

【讨论】:

    【解决方案2】:

    这对线程同步有何帮助?

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

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

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

    如果你写

    m_value = 5;
    m_flag = 1;
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-19
      • 2021-04-27
      • 2017-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多