7

考虑以下两种在currentPrice100...之间获得更大数字的替代方案

int price = currentPrice > 100 ? currentPrice : 100

int price = Math.Max(currentPrice, 100)

我提出这个问题是因为我在考虑currentPrice变量可以被其他线程编辑的上下文。

在第一种情况下......price可以获得低于100

我正在考虑以下问题:

if (currentPrice > 100) {
    //currentPrice is edited here.
    price = currentPrice;
}
4

4 回答 4

8

它不是线程安全的。

?:只是 normal 的快捷方式if,因此您的if示例相当于?一个 - 如果在此代码之外没有锁定,您可以获得低于 100 的价格。

于 2012-10-13T06:33:55.370 回答
3

理论上,currentPrice 会被读取两次。一次比较,一次分配。

在实践中,编译器可能会缓存对变量的访问。我不知道 C# 但在 x86 上的 C++ 中:

MOV AX, [currentPrice]
MOV BX, 100 ;cache the immediate
CMP AX, BX
JLE $1      ;if(currentPrice > 100){
MOV AX, BX
$1:         ;}
MOV [BP+price], AX ;price is on the stack.

除非 currentPrice 被声明为 volatile,否则 Java 字节码中会发生相同的 load-once 优化。

因此,从理论上讲,它可能会发生。实际上,在大多数平台上,它不会,但你不能指望它。

于 2012-10-13T06:49:25.090 回答
3

不是 C# 方面的专家,但即使 var++ 也不是线程保存,因为可以转换为从汇编中的寄存器读取/写入。

三元运算符要复杂得多。它有 3 个部分,而每个部分都可以无限大(例如调用某个函数)。因此,很容易得出三元运算符不是线程安全的结论。

于 2012-10-13T06:51:25.257 回答
1

正如其他人所说,它可能会被缓存,但语言不需要它。

如果您需要无锁线程安全分配,您可以使用Interlocked.CompareExchange 。但是给出这个例子,我会选择更粗粒度的锁定策略。

于 2012-10-13T07:08:28.587 回答