C# Interlocated.CompareExchange单线程等效代码

C# Interlocated.CompareExchange单线程等效代码,c#,thread-safety,interlocked,C#,Thread Safety,Interlocked,我不知道为什么,但我似乎不太明白在联锁的.compareeexchange(参考inta,intb,intc)中发生了什么 如果它只是简单地在单线程环境中实现,有人能告诉我它将做什么吗 i、 e.用“do that…but as a atomic,thread safe operation”替换什么代码?以下是我对代码的理解(在单线程领域): 摘自此处的文档: 参数 位置1(Int32) 目的地,其值与comparand进行比较并可能被替换 值(Int32) 如果比较结果相等,则替换目标值的值

我不知道为什么,但我似乎不太明白在
联锁的.compareeexchange(参考inta,intb,intc)
中发生了什么

如果它只是简单地在单线程环境中实现,有人能告诉我它将做什么吗


i、 e.用“do that…but as a atomic,thread safe operation”替换什么代码?

以下是我对代码的理解(在单线程领域):

摘自此处的文档:

参数

  • 位置1(Int32)
    目的地,其值与comparand进行比较并可能被替换
  • 值(Int32)
    如果比较结果相等,则替换目标值的值
  • 比较数据(Int32)
    与位置1处的值进行比较的值
  • 返回(Int32)
    位置1中的原始值
备注


如果比较符和位置1中的值相等,则该值存储在位置1中。否则,不执行任何操作。比较和交换操作作为原子操作执行。CompareExchange的返回值是位置1中的原始值,无论交换是否发生。

在单线程连接中,该代码的意思是(我相信):
如果(a==c){a=b;}
。由于它读取两个操作数,然后作为单个操作的一部分进行写入,因此它自然不是原子的。
CompareExchange
调用使其原子化(英特尔体系结构机器有一个原子指令来执行此操作-在其他机器上,它可能涉及某种锁)
ref int
不能为空。第一个参数是ref,因为它被读取(作为
if
的一部分)并可能被写入。但是,它从来都不是空的。我也认为你的逻辑是错误的。
if
条件是正确的,但是代码应该是
if(location1==comparand){location1=value;}
Interlocated.CompareeExchange的文档说,如果location1是空指针,它会抛出ArgumentNullException。你说得对,我确实犯了一个错误,但这是一个幼稚的实现@Xtros:它确实(说它抛出)。但是,请尝试编译代码。您将看到
警告CS0472:表达式的结果总是“false”,因为类型为“int”的值永远不等于类型为“int”的“null”?
问题的目的是大致了解Interlocated.CompareExchange的功能。如果您愿意,我可以将其更改为伪代码,但这只是一个粗略的概念。提供有关CompareExchange技术性的更多信息。感谢您复制答案。啊,但您在我开始编写代码后编辑了答案。您的原始代码是错误的。@Flydog57谢谢,这帮助您将所有内容都安排妥当。下一个问题是:“这到底是什么返回值!?”()嗯,为什么不是?否则,旧值将丢失。您知道
value
comparand
的值。唯一更改的值是
location1
的值。如果你想要的话,把它交回去可以让你保存它。
int CompareExchange(ref int location1, int value, int comparand)
{
    if (location1 == null)
        throw new ArgumentNullException(nameof(location1));

    if (location1 != comparand)
    {
        return location1;
    }

    int originalValue = location1;
    location1 = value;
    return originalValue;
}
static int CompareExchange(ref int location1, int value, int comparand)
{
    var valueToReturn = location1;
    if (location1 == comparand)
    {
        location1 = value;
    }

    return valueToReturn;
}