【发布时间】:2011-10-05 03:29:36
【问题描述】:
System.Threading.Interlocked.CompareExchange 运算符提供了比较与交换操作的原子(因此是线程安全的)C# 实现。
例如int i = 5; Interlocked.CompareExchange(ref i, 10, 5); 在这个命令之后,int i 的值 = 10。而且比较和交换也是原子发生的(单个操作)。
当我尝试将它与类实例一起使用时,比较失败并且没有交换值。
public class X
{
public int y;
public X(int val) { y = val; }
}
当我这样做的时候
X a = new X(1);
X b = new X(1);
X c = new X(2);
Interlocked.CompareExchange<X>(ref a, c, b);
比较和交换操作失败。因此,我将 X 类的 Equals 和 == 运算符重写为
public override bool Equals(object obj) { return y == ((X) obj).y; }
所以,现在我得到 Interlocked.Equals(a,b) 为 true,但 CompareExchange 操作仍然失败。
有什么方法可以做到这一点吗?我想比较两个类实例并根据比较为其中一个分配一个值。
【问题讨论】:
-
我猜 CompareExchange 使用 ReferenceEquals 来比较 a 和 b,这是有道理的。您的 Equals 覆盖仅推荐用于不可变类型,您是否仔细考虑过您想要/需要什么 Equals 行为?
-
不幸的是,没有记录,在这种情况下如何确定相等性。
-
@Henk 假设我想要上述行为,其中两个类实例在其成员
y具有相同值时相等。 -
正如@jaff 下面解释的那样,这不能成为原子的。
-
你的例子坏了。 “在此命令之后,int i 的值 = 10” - 仅当
CompareExchange返回的值是 5(或 10 :-))。这可能是简化的示例代码,但我看到了 很多 损坏的代码,人们忘记了在继续之前需要检查CompareExchange是否成功。
标签: c# .net multithreading interlocked