以下示例来自MSDN。
public class ThreadSafe
{
// Field totalValue contains a running total that can be updated
// by multiple threads. It must be protected from unsynchronized
// access.
private float totalValue = 0.0F;
// The Total property returns the running total.
public float Total { get { return totalValue; }}
// AddToTotal safely adds a value to the running total.
public float AddToTotal(float addend)
{
float initialValue, computedValue;
do
{
// Save the current running total in a local variable.
initialValue = totalValue;
// Add the new value to the running total.
computedValue = initialValue + addend;
// CompareExchange compares totalValue to initialValue. If
// they are not equal, then another thread has updated the
// running total since this loop started. CompareExchange
// does not update totalValue. CompareExchange returns the
// contents of totalValue, which do not equal initialValue,
// so the loop executes again.
}
while (initialValue != Interlocked.CompareExchange(ref totalValue,
computedValue, initialValue));
// If no other thread updated the running total, then
// totalValue and initialValue are equal when CompareExchange
// compares them, and computedValue is stored in totalValue.
// CompareExchange returns the value that was in totalValue
// before the update, which is equal to initialValue, so the
// loop ends.
// The function returns computedValue, not totalValue, because
// totalValue could be changed by another thread between
// the time the loop ends and the function returns.
return computedValue;
}
}
应该将totalValue声明为volatile以获得最新的值吗?如果从CPU缓存获取了一个脏值,那么对Interlocked.CompareExchange的调用应该处理获取最新的值并导致循环再次尝试。使用volatile关键字可能会节省一个不必要的循环吗?
我想即使没有 volatile 关键字也不是绝对必要的,因为该方法有重载,可以接受不支持volatile关键字的数据类型,比如long。
Volatile.Read
如何减少在尝试 CAS 时数值过期的可能性?我认为问题的前提是错误的,正如我在我的回答中指出的那样。 - Peter CordesVolatile.Read
可以确保transformer
仅在实际可见的值(至少在本地)上调用,而不是“撕裂”读取(如果它是宽类型)。 (例如,如果转换可以对超出范围的值执行某些错误操作)。您关于跳过CAS的原因(1)当然证明了这一点;如果伪造的值转换为自身,则永远无法达到CAS。也许还有一些有用的效果我没有考虑到,但我认为您的原因(2)没有意义。 - Peter Cordes