C# 联锁-何时使用?

C# 联锁-何时使用?,c#,C#,我刚刚发现了联锁类,现在我有一些基本问题 根据我的理解,我应该在多线程处理数值变量时使用Interlocked。若那个句话是真的,那个么进行读取或者只是一般地使用变量呢 例如: if ((iCount % 100) == 0) 我需要在那里使用联锁的语句吗 当我初始化变量时会发生什么情况: Int32 iCount = 0; Int32 iCount = 0; 在实现它之前,我需要确保我理解这一点。在共享、可变状态上执行多线程时,需要同步。您不需要使用联锁联锁适用于高级用户。我建议您使用l

我刚刚发现了
联锁
类,现在我有一些基本问题

根据我的理解,我应该在多线程处理数值变量时使用Interlocked。若那个句话是真的,那个么进行读取或者只是一般地使用变量呢

例如:

if ((iCount % 100) == 0)
我需要在那里使用
联锁的
语句吗

当我初始化变量时会发生什么情况:

Int32 iCount = 0;
Int32 iCount = 0;

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

在共享、可变状态上执行多线程时,需要同步。您不需要使用
联锁
<代码>联锁
适用于高级用户。我建议您使用
lock
C#语句,仅在简单情况(增加共享计数器)或性能关键情况下使用
Interlocked

联锁
一次只能用于访问单个变量,并且只支持非常原始的操作。您将很难将多个变量与
互锁
同步


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

这里有各种因素,但主要是波动性和原子性。在你的声明中:

我需要在那里使用联锁语句吗

我们首先需要问“什么是
iCount
?”。如果它是
长的
/
ulong
,则不能保证它是原子的,因此您绝对需要某种保护(例如通过
联锁的
)来避免获得“撕裂”值(在更新过程中读取它,给出一个它从未实际存在过的幻像值-例如,从
00000000
更改为
FFFFFFFF
,您可以读取
0000FFFF
ffffff0000
)。如果它是一个
int
,它将被保证是原子的。下一个问题是:我需要看到更新吗?CPU内置了各种级别的缓存,看起来从字段中读取的代码可能最终只是从本地寄存器或缓存中读取,而从来不会触及实际内存。如果这是一个风险,那么您可以减轻这一风险t通过使用
联锁
,尽管在许多情况下使用
易失性
也可以防止这种情况

在讨论更新时,第三个棘手的问题出现了:是否希望“最后一次编辑盲目获胜”?如果是,只需更新值(可能使用
volatile
允许读取)-但是-如果两个线程正在编辑,则有丢失更新的风险。例如,如果两个线程同时递增和递减,则最终值可能是
0
1
-不一定是您想要的值。
intelock
提供了使用更改检测进行更新的方法,以及执行常见操作的辅助方法增量/减量/添加/等运算

你的另一个问题是:

当我初始化变量时会发生什么情况:

Int32 iCount = 0;
Int32 iCount = 0;
字段初始值设定项只在一个线程上执行,因此不需要额外的保护-这很好


但是!线程是很难的。如果您完全不确定,请保持简单:使用
lock
。例如(假设您需要每个实例同步):


在许多情况下,这很好。

我想补充一下Microsoft另外引入了ImmutableInterlocked类的其他答案

此类用于处理不可变集合。该类具有一组函数,用于使用比较和交换模式更新不可变集合

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


可能重复:我看到了那篇文章,但它跳过了我的基本问题。在我的例子中,iCount是一个Int32@JeffV是的,但在我看来,你需要明白这很重要,因此我才把它包括在答案中。如果我只是说“是的,那是原子弹”,那就很危险了没有上下文,因为在实际代码中可能会将其更改为
long
。同样,原子性只是故事的一部分。感谢您的澄清。我正在研究锁(syncLock)立即构造。我感谢你的回答。如果我要插入数据库表,我是否也应该在其周围加锁?@Jeff复杂的问题-数据库有自己的锁定构造。还要记住,数据库锁是跨进程(和跨机器)的,而“锁”是单进程的。