Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 联锁后无锁读取值。交换?_C#_Multithreading_Lock Free_Interlocked - Fatal编程技术网

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
}