I have a simple class and I want to make it thread-safe. The class needs to implement IComparer. I know that implementing the int CompareTo(T other)
in a thread-safe way is not straight-forward. It's easy to allow a deadlock if I don't lock in the right way. I have three questions:
- Is this code thread-safe? If not, how can I fix it?
- Can this code be any shorter? It seems like a lot of code for a simple subtraction.
- Should I even bother making
int CompareTo(T other)
thread-safe? Should I instead require that the caller (usually sorting) lock all of the relevant BObjects?
Here's my code:
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;
}
}