【发布时间】:2026-01-07 15:00:02
【问题描述】:
我有一个简单的类,我想让它成为线程安全的。该类需要实现 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;
}
}
【问题讨论】:
-
锁定每个成员并不能使您的代码线程安全。
-
使比较线程安全的最简单方法:使您的类型不可变。
-
将此评论:
lock the BObject with the higher id first更改为...last -
简而言之,线程安全是hard。您需要弄清楚哪些操作可以同时发生,以及无论发生什么,如何确保您处于一致的状态。不可变对象使这非常更容易做到。
-
@user2023861 字符串是不可变的,所以它们没有问题。您只需放置两个字段。例如 int Sales 和 DateTime LastSale
标签: c# thread-safety locking icomparer