我有一个简单的类,我想让它成为线程安全的。该类需要实现IComparer。我知道以线程安全的方式实现int CompareTo(T other)
并不是直截了当的。如果我没有以正确的方式锁定,很容易出现死锁。我有三个问题:
int CompareTo(T other)
线程安全?我是否应该要求调用者(通常是排序)锁定所有相关的BObject?这是我的代码:
public class BObject : IComparable<BObject>
{
//Each BObject has a unique object id
private static int _bObjectId = 0;
private static int GetNextId()
{
return System.Threading.Interlocked.Increment(ref BObject._bObjectId);
}
private object _locker = new object();
private readonly int _id = BObject.GetNextId();
//Some variable
private int _sales;
public int Sales
{
get
{
lock (this._locker)
return this._sales;
}
set
{
lock (this._locker)
this._sales = value;
}
}
public int CompareTo(BObject other)
{
int result;
//Can I simply do "if (this._id == other._id)"
if (object.ReferenceEquals(this, other))
result = 0;
else
{
//get the BObject with the lower id
BObject lower = this._id < other._id ? this : other;
//get the BObject with the higher id
BObject higher = this._id > other._id ? this : other;
//lock the BObject with the lower id first
lock (lower._locker)
{
//lock the BObject with the higher id last
lock (higher._locker)
{
//put object with lower Sales first
result = this.Sales - other.Sales;
}
}
}
return result;
}
}
答案 0 :(得分:2)
在什么使用条件下,您期望这种比较与被比较的值的突变同时发生?在这种情况下,什么行为应该是正确的?#?一旦定义了正确性标准,就可以设计一种方法来实现如何通过线程安全来实现它。
线程安全实际上是关于如何使用事物以及这种用法如何跨线程边界进行交互。因此,例如,如果您要对这些对象的列表进行排序,然后同时对集合进行变更,那么您可能需要一些方法来防止在排序过程中发生突变。最糟糕的情况是,你可以想出一个场景,你以一种导致排序永远不会终止的方式改变实例(这样做很麻烦,但理论上可行。)总之,你需要多想想关于您如何使用这些实例的高级视角。最有可能的是,这不是可以制作和线程安全的东西。在实例访问者级别。