gpt4 book ai didi

c# - Interlocked.CompareExchange(引用值,newValue,compareTo)

转载 作者:行者123 更新时间:2023-11-30 23:31:32 28 4
gpt4 key购买 nike

using System;
using System.Threading;
using System.Threading.Tasks;

namespace _1._41_Compare_and_Exchange_as_a_nonAtomic_operation
{
public class Program
{
static int value = 1;

public static void Main()
{

Task t1 = Task.Run(() =>
{
if (value == 1)
{

Thread.Sleep(1000);

value = 2;

}
});

Task t2 = Task.Run(() =>
{
value = 3;

});

Task.WaitAll(t1, t2);
Console.WriteLine(value); //Displays 2

}
}
}

我正在尝试将上述非原子操作转换为原子操作,方法是:

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

我写成

 Interlocked.CompareExhange(ref value, value, value); //This doesn't look right!

Interlocked.CompareExhange(ref value, t2, t1); //will not compile

问题

  1. 有或没有 Interlocked.CompareExchange 值输出为 2?为什么?
  2. 引用 t1、t2 的正确方法是什么?
  3. 为什么我不能直接引用任务的输出? (值,t2,t1)
  4. 是否需要或什至必须进行某种转换?
  5. 据我所知,该值应更新为 2(值 = 1),然后更新为 3,而不是当前输出(值 = 1,更新为 3,然后更新为 2)一次 Interlocked.CompareExchange被使用?

最佳答案

With or without Interlocked.CompareExchange value is output as 2? Why?

真正的答案是:巧合。您的代码是不确定的,其行为取决于操作系统线程调度程序。

但是... t1 实际上一点也不奇怪在 t2 之前开始执行.在这种情况下,if (value == 1)检查在 t2 之前进行有机会执行value = 3; .

综上所述,最有可能的时间线是:

  • t1 : value根据 1 检查
  • t1 : t1睡一秒钟
  • t2 : value设置为 3
  • t1 : 一秒钟后醒来
  • t1 : value设置为 2

但是正如我上面所说的,这只是实际发生的情况,但是游览代码仍然是不确定的,如t2 可以原则上在t1之前开始执行.

What is the correct way to reference t1, t2?

如果我正确理解你的问题,你的做法似乎是正确的。

Why can't I reference the output of the task directly? (value, t2, t1)

你开始void任务,它们一开始就没有输出。它们由 Task 表示类型。

您可以启动一个返回如下结果的任务:

var t = Task.Run(() => {
// do anything
return 42;
});

在这种情况下,t将是 Task<int> 类型你将能够访问它的 Result任务结束时的属性(如果您尝试在任务完成之前访问 i,它将阻塞直到任务结束)。

Is some sort of conversion required or even necessary?

我不确定我是否理解您的问题。

As I understand the value should be updated to 2 (value =1) then updated to 3 instead of the current output (value =1, updates to 3 then updates it to 2) once Interlocked.CompareExchange is used?

差不多,是的。 Interlocked.CompareExchange原子的。它将执行比较在硬件级别一步设置值:

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

这是原子等价于:

if (value == 1)
value = 2;

如果您这样做,最终值将始终3 .因为可能有两种不同的场景(这很容易,因为现在两个任务都包含一个原子语句):

  • t1t2 之前执行:

    • t1 : value根据 1 检查,这是真的,所以 value设置为 2
    • t2 : value设置为 3
  • t2t1 之前执行:

    • t2 : value设置为 3
    • t1 : value根据 1 检查,这是错误的,所以 value保持不变

如您所见,您最终会得到 3在这两种情况下。

关于c# - Interlocked.CompareExchange(引用值,newValue,compareTo),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34559084/

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