繁体   English   中英

Interlocked.Exchange之后的Lockfree Read值?

[英]Lockfree Read value after Interlocked.Exchange?

让我们说我们有这样一个类:

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();
    }
}

并且假设我们有两个线程,一个在DoStuffInThread1DoStuffInThread1 ,另一个在OtherStuffFromThread2OtherStuffFromThread2

如何确保thread2始终看到最新的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()上使用等待thread1准备就绪的方法都会导致一个隐含的内存障碍 ...参见例如内存屏障生成器一些导致内存障碍的结构......

所以:

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

读取volatile字段称为volatile读取。 易失性读取具有“获取语义”; 也就是说,保证在指令序列之后发生的任何内存引用之前发生。

所以,如果你这样做:

private static int myuselessvolatilefieldthatcanbestatic;
private int thefieldiwanttoread;

接着

var useless = myuselessvolatilefieldthatcanbestatic;
var iwanttoknow = thefieldiwanttoread;

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

请注意,如果没有同步原语,很难知道什么时候可以完成myuselessvolatilefieldthatcanbestatic :-),但是:

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

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

如果要读取最新的可用值,则应使用Interlocked.CompareExchange(ref bar, null, null) 检查null只是为了满足CompareExchange签名(如果barnull ,则将其设置为null )。 这将为您提供执行时CPU中可用的最新值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM