我现在已经多次看过上面提到的代码片段了,做Max(a+1, a-1)
的重点是什么?起初我认为可能是为了防止下溢,但在这种情况下不防止下溢是没有意义的。
答案 0 :(得分:5)
一些谷歌搜索让我怀疑这可能是由于某些(可能是错误的)C#到VB.NET转换器软件引起的。这可以解释它的频繁出现。
已添加: Yessss,我found it!尝试在其中输入以下C#代码并转换为VB.NET:
int i;
i++;
答案 1 :(得分:4)
正如您所提到的,他们可能会尝试检测何时Offset
包裹为零(或变为负数),并将其与任何类型Offset
的最大值挂钩。或者他们可能正试图处理Offset
在多个线程(或其他东西)中同时“递增”的情况。
在任何一种情况下,这都是错误的代码。
如果他们试图检测/阻止换行为零或负数,则过多的增量将导致问题无论如何。如果他们试图同时处理Offset
递增',我不确定他们真正试图解决的问题或他们试图如何解决它。
以下是问题:
然而,对我来说这听起来仍然很奇怪 - 因为除非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
为什么在这种情况下使用它我不能说没有看到更多的代码。