簡體   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