Max(Threading.Interlocked.Increment(Offset),Offset - 1)有什么意义?

时间:2009-04-19 16:41:52

标签: c# .net multithreading

我现在已经多次看过上面提到的代码片段了,做Max(a+1, a-1)的重点是什么?起初我认为可能是为了防止下溢,但在这种情况下不防止下溢是没有意义的。

4 个答案:

答案 0 :(得分:5)

一些谷歌搜索让我怀疑这可能是由于某些(可能是错误的)C#到VB.NET转换器软件引起的。这可以解释它的频繁出现。

已添加: Yessss,我found it!尝试在其中输入以下C#代码并转换为VB.NET:

int i;
i++;

答案 1 :(得分:4)

正如您所提到的,他们可能会尝试检测何时Offset包裹为零(或变为负数),并将其与任何类型Offset的最大值挂钩。或者他们可能正试图处理Offset在多个线程(或其他东西)中同时“递增”的情况。

在任何一种情况下,这都是错误的代码。

如果他们试图检测/阻止换行为零或负数,则过多的增量将导致问题无论如何。如果他们试图同时处理Offset递增',我不确定他们真正试图解决的问题或他们试图如何解决它。

以下是问题:

As Jon Skeet says

  

然而,对我来说这听起来仍然很奇怪 - 因为除非Offset是易失性的,否则后一种表达式可能无法获得最新值。

但它甚至比这更糟糕 - 即使Offset是易变的,也没有什么可以序列化读取Offset的新值与另一个可能递增它的线程,所以在{{Max()之后的瞬间1}}表达式重新读取Offset的值,可以出现任意数量的其他线程并增加它(任意次数)。所以充其量,表达式是无用的,但使用该技术可能是有害的,因为您最终可能会使用不属于您的Offset值。

考虑一下你使用Offset来跟踪数组索引或其他东西的情况(给出的名称听起来就像可能发生的那样)。当您以原子方式递增Offset时,该索引处的数组元素将成为您的使用者。如果你在问题中使用Max()表达式,你可能会突然想到一个真正属于另一个线程的数组元素。

我想不出使用

的正当理由
Max(Threading.Interlocked.Increment(Offset), Offset - 1)

就像我说的那样,充其量只是无害(无用),但它可能会引入 非常 难以诊断问题 - 不要使用它强>


感谢Simon Svensson的评论指出谷歌搜索问题中的用法,看起来这个代码通常(总是?)来自C#到VB.NET转换器的输出。它甚至使用此表达式来增加局部变量(因此线程不是问题)。在Offset是局部变量的情况下,这个表达式属于无用但几乎无害的变体(如果增量包装,将会出现'bug')。它实际上或多或少是一个非常低效的Offset++表达式(实际上它似乎是转换器将C#表达式Offset++转换为VB.NET的方式 - 请参阅http://www.telerik.com/community/forums/open-source-projects/code-converter/added-value.aspx#307755)。实际上这个转换对于Offset++来说是错误的,因为当它应该在递增之前返回值时返回递增的值。

真正糟糕的是,其他人可能会查看该代码并思考,“这就是我需要使用Interlocked.Increment()”的方式。

答案 2 :(得分:2)

嗯,它与Max(a, a-1)不一样 - 因为有Interlocked.Increment的号召。假设另一个线程在调用Interlocked.Increment和评估Offset-1之间更改了Offset的值。

然而,对我来说这听起来仍然很奇怪 - 因为除非Offset是易变的,否则后一个表达式可能无法获得最新值。

说完这一切之后,代码不能完全

Math.Max(Interlocked.Increment(Offset), Offset-1)

因为Interlocked.Increment的参数是ref参数。最接近的法律代码是:

Math.Max(Interlocked.Increment(ref Offset), Offset-1)

(这仍然是奇怪的,因为它意味着一个基于Pascal的变量...)

也许如果你能在上下文中显示确切的代码,我们可以解决问题。我不能说我自己见过这样的代码。

答案 3 :(得分:1)

Interlocked.Increment(a)以原子方式递增a的值。在单线程应用程序中,它等同于a++,但速度稍慢。在多线程应用程序中,它确保当两个线程递增值时,它们不会相互干扰。有关详细信息,请参阅MSDN reference page

为什么在这种情况下使用它我不能说没有看到更多的代码。