gpt4 book ai didi

c# - 使用原子操作锁定

转载 作者:太空狗 更新时间:2023-10-29 22:54:07 25 4
gpt4 key购买 nike

是的,我知道可以用“改用 lock 关键字”或类似的东西来回答以下问题。但因为这只是为了“好玩”,所以我不关心这些。

我使用原子操作做了一个简单的锁:

public class LowLock 
{
volatile int locked = 0;

public void Enter(Action action)
{
var s = new SpinWait();

while (true)
{
var inLock = locked; // release-fence (read)

// If CompareExchange equals 1, we won the race.
if (Interlocked.CompareExchange(ref locked, 1, inLock) == 1)
{
action();
locked = 0; // acquire fence (write)
break; // exit the while loop
}
else s.SpinOnce(); // lost the race. Spin and try again.
}
}
}

我在一个简单的 for 循环中使用了上面的锁,它将一个字符串添加到一个普通的 List<string> 中。 , 目的是制作 add方法线程安全,当包裹在 Enter 中时来自 LowLock 的方法.

代码如下:

static void Main(string[] args)
{
var numbers = new List<int>();

var sw = Stopwatch.StartNew();
var cd = new CountdownEvent(10000);

for (int i = 0; i < 10000; i++)
{
ThreadPool.QueueUserWorkItem(o =>
{
low.Enter(() => numbers.Add(i));
cd.Signal();
});
}

cd.Wait();
sw.Stop();

Console.WriteLine("Time = {0} | results = {1}", sw.ElapsedMilliseconds, numbers.Count);

Console.ReadKey();
}

现在棘手的部分是当主线程命中 Console.WriteLine 时打印时间和列表中元素的数量,元素的数量应该等于给CountdownEvent的计数(10000) - 它在大多数情况下都有效,但有时列表中只有 9983 个元素,有时是 9993 个。我忽略了什么?

最佳答案

我建议你看看 SpinLock 看起来完全符合您的要求的结构。


也就是说,这一切看起来都很冒险,但我会尝试一下。

您似乎尝试使用0意思是“解锁”和1意思是“锁定”。

在这种情况下行:

if (Interlocked.CompareExchange(ref locked, 1, inLock) == 1)

根本不正确。它只是替换了 locked值为 1 的变量(锁定)如果它的当前值与你上次通过 inLock = locked 读取的值相同(如果是这样,则获取锁)。更糟糕的是,如果原始值为 1,它进入了互斥部分。 (锁定),这与您想要做的完全相反

您实际上应该通过使用 0 原子地检查锁是否未被占用(原始值 == 0)并在可以时占用它(新值 == 1) (解锁)既是comparand参数以及用于测试返回值的值:

if (Interlocked.CompareExchange(ref locked, 1, 0) == 0)

现在即使你修复了这个,我们也需要确定 List<T>.Add方法将“查看”列表的最新内部状态以正确执行追加。我认为 Interlocked.CompareExchange使用一个完整的内存屏障,它应该会产生这种令人愉快的副作用,但是依赖它似乎有点危险(我从未在任何地方看到过这个记录)。

除非您是真正的低锁编程专家,否则我强烈建议您远离此类低锁模式,除非是在最微不足道(并且显然)的场景中。我们凡人弄错。

编辑:将比较值更新为 0 .

关于c# - 使用原子操作锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8038889/

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