C# 联锁后无锁读取值。交换?
假设我们有这样一门课:C# 联锁后无锁读取值。交换?,c#,multithreading,lock-free,interlocked,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
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
上运行,另一个在otherstuffromthread2
上运行
如何确保thread2始终能看到最新的条
?
这没用。我不想要老式的锁。
必须有一种方法来读取mem屏障/以某种方式联锁的棒的正确值?您错过了要点 除非你这样做:
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就绪的方法都会导致隐式内存载体。。。例如,请参阅导致memorybarriers的一些构造
因此:
如果确实要读取变量的值,可以先读取一个volatile变量,然后再读取变量(或者读取同一个volatile变量两次)。为什么?由于易失性读取会导致获取语义,这意味着它不能通过后续内存操作重新排序,请参阅:
对易失性字段的读取称为易失性读取。易失性读取具有“获取语义”;也就是说,在指令序列中,它保证发生在对内存的任何引用之前,而对内存的任何引用发生在它之后
因此,如果你这样做:
private static int myuselessvolatilefieldthatcanbestatic;
private int thefieldiwanttoread;
然后
var useless = myuselessvolatilefieldthatcanbestatic;
var iwanttoknow = thefieldiwanttoread;
字段diwanttoread
将包含一个值,该值将在新读取完Canbestatic的MyUselessVolatileField后读取
请注意,如果没有同步原语,将很难知道何时将完成CanBestatic的MyUselessVolatileField:-),但是:
现在至少可以使用while(true)
:-)如果要读取最新的可用值,应该使用类似Interlocked.CompareExchange(参考条,null,null)
的内容。检查null只是为了满足CompareExchange签名(如果bar
是null
,那么它会将其设置为null
)。这将为您提供执行时CPU中可用的最新值。您好,收到!:-)我很好奇为什么volatile没有帮助?我可能在这里遗漏了一些东西……线程2怎么知道在Bar
中甚至应该有一个“最新”的条呢?@DanByström我不知道它背后的机制,但它不起作用,即使在交换之后,线程2仍然和线程1在同一个对象上运行。这很奇怪。我本以为应该…:-/
var useless = myuselessvolatilefieldthatcanbestatic;
var iwanttoknow = thefieldiwanttoread;
while (true)
{
var useless = myuselessvolatilefieldthatcanbestatic;
var iwanttoknow = thefieldiwanttoread;
// Some code goes here
}