繁体   English   中英

连锁-何时使用?

[英]interlocked - when do I use it?

我刚刚了解了Interlocked类,现在有一些基本问题。

据我了解,多线程处理数字变量时应该使用互锁。 如果该说法是正确的,那么如何进行读取或只是常规使用变量呢?

例如:

if ((iCount % 100) == 0)

我是否需要在此处使用“ Interlocked语句?

当我初始化变量时该怎么办:

Int32 iCount = 0;

在实施之前,我需要确保我理解这一点。

这里有多种因素,但主要是波动性原子性 在您的陈述中:

 if ((iCount % 100) == 0) 

我是否需要在此处使用“互锁”语句?

我们首先需要问“什么是iCount ?”。 如果它是long / ulong ,那么就不能保证它是原子的 ,因此,您绝对需要某种保护(例如通过Interlocked )来避免获得“撕裂”的值(在更新过程中读取它,给出一个幻像值,它实际上从未真正是-例如,从00000000更改为FFFFFFFF您可以读取0000FFFFFFFF0000 如果它是int ,则将保证它是原子的。 下一个问题是:我需要查看更新吗? CPU具有内置的各种缓存级别, 看似从字段读取的代码实际上只能从本地寄存器或缓存中读取,而永远不会触及实际内存。 如果存在这种危险,则可以使用Interlocked减轻风险,尽管在很多情况下,使用volatile也可以避免这种情况。

在讨论更新时出现第三个棘手的问题:您是否要“最后编辑盲目获胜”? 如果是这样,则仅更新值(大概使用volatile允许读取)-但是,如果两个线程正在编辑,则存在丢失更新的风险。 例如,如果两个线程分别同时递增和递减,则最终值可以为01不一定是您想要的值。 Intelocked提供了使用更改检测进行更新的方法,以及辅助方法来执行常见的操作,例如递增/递减/添加/等。

再问另一个问题:

当我初始化变量时该怎么办:

 Int32 iCount = 0; 

字段初始化程序仅在一个线程上执行,因此不需要额外的保护-很好。


然而! 线程很难。 如果完全不确定,请保持简单:使用lock 例如(假设您要按实例进行同步):

private int iCount = 0;
private readonly object syncLock = new object();
...
lock(syncLock) {
    // code that reads or manipulates iCount
}

在许多情况下,这可以正常工作。

在共享的可变状态上进行多线程处理时,您需要同步。 不需要使用Interlocked Interlocked适用于高级用户。 我建议您使用lock C#语句,并且仅在发生简单情况(增加共享计数器)或对性能要求较高的情况下使用Interlocked

Interlocked只能一次访问单个变量,并且仅支持非常原始的操作。 使用Interlocked同步多个变量将非常困难。

在您的示例中,没有人可以告诉您是否需要同步,因为线程安全性是整个程序的属性,而不是单个语句或函数的属性。 您需要将所有在共享状态下运行的代码视为一个整体。

我想补充其他答案,微软另外引入了ImmutableInterlocked类。

此类用于处理不可变集合。 该类具有一组用于使用Compare-And-Swap模式更新不可变集合的函数。

您可以在System.Collections.Immutable命名空间中找到它。

https://msdn.microsoft.com/zh-CN/library/system.collections.immutable.immutableinterlocked(v=vs.111).aspx

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM