C#中的三元运算符(?:)线程是否安全?

时间:2012-10-13 06:30:27

标签: c# thread-safety ternary-operator

考虑以下两种方法,在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 个答案:

答案 0 :(得分:8)

这不是线程安全的。

?:只是正常if的快捷方式,因此您的if样本相当于?一个 - 如果外面没有锁定,您可以获得低于100的价格这段代码。

答案 1 :(得分: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字节码中会发生相同的一次加载优化。

所以,从理论上讲,它可能会发生。在实践中,在大多数平台上,它不会,但你不能指望它。

答案 2 :(得分:3)

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

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

答案 3 :(得分:1)

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

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