2013-08-16 21 views
-1

我有一个简单的类,我想使它线程安全。该类需要实现IComparer。我知道以线程安全的方式实施int CompareTo(T other)并不是直截了当的。如果我不以正确的方式锁定,那么容易造成死锁。我有三个问题:这是如何编写线程安全IComparable?

  1. 此代码是否线程安全?如果不是,我该如何解决?
  2. 此代码可以缩短吗?它看起来像一个简单的减法很多代码。
  3. 我应该甚至打扰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; 
    } 
} 
+4

锁定每个成员不会使您的代码线程安全。 – SLaks

+0

特别是,'int's已经是原子的;你根本不需要锁。 – SLaks

+3

使比较线程安全的最简单方法:使您的类型不可变。 –

回答

2

在你期望的突变的值进行比较这种比较在同一时间发生的情况使用条件?在这些条件下,什么样的行为应该是“正确的”?一旦你定义了正确性的标准,你可以设计一个方法来实现线程安全。

线程安全性的确是关于如何使用事物以及这种用法如何跨越线程边界进行交互。因此,例如,如果您排序这些对象的列表,然后同时突变该集合,则可能需要某种方法来防止在排序过程中发生突变。最糟糕的情况是,你可以想出一个场景,你可以用一种导致排序永不终止的方式来突变实例(这样做很棘手,但理论上可行。)总之,你需要更多地考虑您对如何使用这些实例的高级视角。最有可能的是,这不是在实例访问器级别上可以'线程安全'的东西。

+0

'你可能想要某种方式来防止在排序过程中发生突变'这是我关于第三个问题的想法。在这种情况下,让我的'CompareTo'方法是线程安全的是没有意义的。 – user2023861