2013-08-16 46 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