c# - Interlocked.Exchange 后无锁读取值?

标签 c# multithreading lock-free interlocked

假设我们有这样一个类:

public class Foo
{
     private Bar bar = new Bar();

    public void DoStuffInThread1()
    {
        var old = Interlocked.Exchange(ref bar,new Bar());
        //do things with old
        //everything is fine here, I'm sure I have the previous bar value
    }

    public void OtherStuffFromThread2()
    {
        //how do I ensure that I have the latest bar ref here
        //considering mem cahces etc
        bar.Something();
    }
}

假设我们有两个线程,一个在 DoStuffInThread1 上运行,另一个在 OtherStuffFromThread2 上运行。

如何确保线程 2 始终看到最新的 bar? volatile 没有帮助。而且我不想要老派的锁。 必须有一种方法来读取带有内存屏障/以某种方式互锁的 bar 的正确值吗?

最佳答案

你错过了重点......

除非你这样做:

public void OtherStuffFromThread2()
{
    while (true)
    {
        //how do I ensure that I have the latest bar ref here
        //considering mem cahces etc
        bar.Something();
    }
}

这是非常不可能的事情,几乎所有您可以在 OtherStuffFromThread2() 上使用的等待线程 1 准备就绪的方法都会导致隐式内存障碍...参见示例 Memory barrier generators一些导致内存障碍的构造......

所以:

public void OtherStuffFromThread2()
{
    Thread.Sleep(Timespan.FromMinutes(1));
    // Implicit MemoryBarrier here :-)

    //how do I ensure that I have the latest bar ref here
    //considering mem cahces etc
    bar.Something();
}

如果你真的想读一个变量的值,你可以读一个volatile变量然后读你的变量(或者读同一个volatile变量两次)。为什么?因为 volatile 读取会导致获取语义,这意味着它无法通过后续内存操作重新排序,请参阅 https://msdn.microsoft.com/en-us/library/aa645755(v=vs.71).aspx :

A read of a volatile field is called a volatile read. A volatile read has "acquire semantics"; that is, it is guaranteed to occur prior to any references to memory that occur after it in the instruction sequence.

所以如果你这样做:

private static int myuselessvolatilefieldthatcanbestatic;
private int thefieldiwanttoread;

然后

var useless = myuselessvolatilefieldthatcanbestatic;
var iwanttoknow = thefieldiwanttoread;

thefieldiwanttoread 将包含一个值,该值将在 myuselessvolatilethatcanbestatic 的新读取完成后读取。

请注意,如果没有同步原语,将很难知道 myuselessvolatilefieldthatcanbestatic 何时完成 :-),但是:

while (true)
{
    var useless = myuselessvolatilefieldthatcanbestatic;
    var iwanttoknow = thefieldiwanttoread;
    // Some code goes here
}

现在至少你可以使用你的while (true) :-)

关于c# - Interlocked.Exchange 后无锁读取值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29107314/

相关文章:

c# - 在 C# 中创建 ASN1 编码签名以发送到 Java

java - 安卓 : Get data in real-time instead of using Async-Task

c# - 无锁并发队列

assembly - CMPXCHG——忽略 ZF 标志安全吗?

c++ - 这段代码是线程安全的吗?

c# - 管理过期?轮询与事件

c# - 最小起订量特定列表项的检索

c# - XAML 条件编译

android - 频闪相机参数?为什么我的应用程序崩溃了?

multithreading - 可以在关键部分进行上下文切换吗?