假设我们有一个类似的课程:
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
上运行。
如何确保thread2始终可以看到最新的bar
?
挥发无济于事。而且我不想要旧学校的锁。
必须有一种方法来读取条形码的正确值,并以某种方式互锁?
答案 0 :(得分:2)
你错过了这一点......
除非你这样做:
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准备就绪的方法都会导致隐式内存屏障...例如参见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:
读取volatile字段称为volatile读取。易失性读取具有"获取语义&#34 ;;也就是说,它保证在指令序列之后发生的任何内存引用之前发生。
所以,如果你这样做:
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)
: - )
答案 1 :(得分:1)
如果您想阅读最新的可用值,则应使用Interlocked.CompareExchange(ref bar, null, null)
之类的内容。检查null只是为了满足CompareExchange签名(如果bar
是null
,那么它会将其设置为null
)。这将为您提供执行时CPU中可用的最新值。