C# 这就是如何编写线程安全的IComparable吗?

C# 这就是如何编写线程安全的IComparable吗?,c#,thread-safety,locking,icomparer,C#,Thread Safety,Locking,Icomparer,我有一个简单的类,我想让它线程安全。该类需要实现IComparer。我知道以线程安全的方式实现int CompareTo(T other)并不是一件简单的事情。如果锁定方式不正确,很容易出现死锁。我有三个问题: 这段代码是线程安全的吗?如果没有,我如何修复它 这个代码能再短一点吗?对于一个简单的减法似乎有很多代码 我是否应该麻烦将int CompareTo(T other)设置为线程安全?我是否应该要求调用方(通常是排序)锁定所有相关的BObject 这是我的密码: public class B

我有一个简单的类,我想让它线程安全。该类需要实现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;
        }
    }
    
    公共类对象:i可比较
    {
    //每个对象都有一个唯一的对象id
    私有静态int_bobObjectId=0;
    私有静态int GetNextId()
    {
    返回系统。螺纹。联锁。增量(参考对象);
    }
    私有对象_locker=新对象();
    私有只读int_id=BObject.GetNextId();
    //一些变量
    私人国际销售;
    公开销售
    {
    得到
    {
    锁(这个储物柜)
    退回这个。_销售部;
    }
    设置
    {
    锁(这个储物柜)
    这意味着销售额=价值;
    }
    }
    公共内部比较(对象其他)
    {
    int结果;
    //我是否可以简单地执行“如果(this.\u id==other.\u id)”
    if(object.ReferenceEquals(this,other))
    结果=0;
    其他的
    {
    //获取具有较低id的对象
    BObject lower=此。_id<其他。_id?此:其他;
    //获取具有较高id的对象
    BObject higher=this.\u id>other.\u id?this:other;
    //首先锁定具有较低id的对象
    锁(下部锁柜)
    {
    //最后锁定id较高的对象
    锁(更高的锁)
    {
    //将销售额较低的对象放在第一位
    结果=此.Sales-其他.Sales;
    }
    }
    }
    返回结果;
    }
    }
    
    在什么使用条件下,您希望此比较与被比较值的突变同时发生?在这种情况下,什么行为应该是“正确的”?一旦定义了正确性标准,就可以设计一种方法来实现线程安全性


    线程安全实际上是关于如何使用事物以及这种使用如何跨线程边界进行交互。因此,例如,如果您正在排序这些对象的列表,然后同时对集合进行突变,则可能需要某种方法来防止在排序过程中发生突变。最坏的情况是,您可能会想出一个场景,在这个场景中,您以一种导致排序永远不会终止的方式对实例进行变异(这很难做到,但在理论上是可能的)。简言之,您需要更多地从高层角度考虑如何使用这些实例。最有可能的是,在实例访问器级别,这不是“线程安全”的东西。

    锁定每个成员并不会使代码线程安全。使比较线程安全的最简单方法:使您的类型不可变。更改此注释:
    首先锁定id较高的对象
    …最后一个
    ,线程安全性很难。您需要弄清楚哪些操作可以同时发生,以及如何确保无论发生什么情况,您都处于一致的状态。不可变对象使这一点更容易做到。@user2023861字符串是不可变的,所以它们没有问题。您只需输入两个字段。It Stand和DeaTimeLaStestRead例如“代码”>您可能需要某种方法来防止突变,而在排序< /代码>的过程中,这是我关于我的第三个问题的想法。在这种情况下,将我的
    方法与
    方法进行比较是没有意义的。