gpt4 book ai didi

c# - 比较和交换作为非原子操作

转载 作者:太空宇宙 更新时间:2023-11-03 17:50:45 25 4
gpt4 key购买 nike

我有一个 book about programming in C#.有一个例子。让我复制并粘贴上下文。

...介绍了Interlocked的用法(此处省略)。

You can also use the CompareExchange method. This method first checks to see whether the expected value is there; if it is, it replaces it with another value.

Listing 1-41 shows what can go wrong when comparing and exchanging a value in a nonatomic operation.

LISTING 1-41 Compare and exchange as a nonatomic operation


class Program
{
static int value = 1;
static void Main(string[] args)
{
Task t1 = Task.Run(() =>
{
if(value==1)
{
// Removing the following line will change the output
Thread.Sleep(1000);
value = 2;
}
});
Task t2 = Task.Run(() =>
{
value = 3;
});
Task.WaitAll(t1, t2); // Displays 2
Console.WriteLine(value);
}
}

Task t1 starts running and sees that value is equal to 1. At the same time, t2 changes the value to 3 and then t1 changes it back to 2. To avoid this, you can use the following Interlocked statement:


Interlocked.CompareExchange(ref value, newValue, compareTo);

This makes sure that comparing the value and exchanging it for a new one is an atomic operation. This way, no other thread can change the value between comparing and exchanging it.



本书没有提供更多细节,仅在此结束本节。

我的问题是如何申请 Interlocked.CompareExchange(ref value, newValue, compareTo);到代码?

最佳答案

好吧,我猜他们的意思是替换非原子 block :

if(value==1)
{
// Removing the following line will change the output
Thread.Sleep(1000);
value = 2;
}


Interlocked.CompareExchange(ref value, 2, 1);

编辑,Interlocked.CompareExchange 解决了什么问题?

两个任务 t1 和 t2 都改变了 value ,可能同时发生。

这里的代码序列是多线程代码中常见的反模式 - ABA problem :
if(someUnsynchronizedCondition)
{
... Other random code here
doSomeActionDependentOnTheCheckedCondition();
}

这样做的问题是,检查的条件( if (value==1) )在执行相关操作时(在您的情况下为 value = 2;)不一定为真,因为其他线程可以更改此线程从 if 移动所需的时间相同。检查相关操作(显然,“其他随机代码”花费的时间越多,例如 2 秒 sleep ,风险就越大)。但始终存在风险,即使两者之间没有额外的代码(即,即使完全删除 Thread.Sleep,原始代码仍然容易出现 ABA)。

在本书的示例中,操作是改变条件中使用的相同变量,因此使用 Interlocked.CompareExchange 执行此操作的便捷方法- 对于 Intel 处理器,这转换为单个 lock cmpxchg [reg1], reg2 atomic instruction .

在更一般的意义上(即依赖操作不仅仅是更改检查变量),您需要使用其他同步方式,例如 lockReaderWriterLockSlim ,尤其是在读者多于作者的情况下。

Re: 最终结果

是的,代码现在总是显示 3,因为如果第一个 Task t1 首先执行,它会将值更改为 2,这将被第二个 Task 否决t2 将其设置为 3,但如果第二个任务首先运行(设置为 3),则 t1 不会更新该值,因为它是 3,而不是 1。

关于c# - 比较和交换作为非原子操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27800749/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com