2011-02-28 39 views
1

我有一個對象的靜態集合,將頻繁更新多個線程。是否可以鎖定集合中的單個對象而不是鎖定整個集合,以便只有嘗試訪問集合中同一對象的線程纔會被阻塞而不是每個線程?鎖定靜態集合中的單個元素?

如果有更好的方法來更新來自多個線程的集合中的對象,我完全耳熟能詳。

+0

使用鎖對象爲每個項目 – 2011-02-28 23:21:48

+0

看看這裏接受的答案:[線程安全緩存庫的.NET](http://stackoverflow.com/questions/2330275/thread-safe-cache-庫換網) – 2011-02-28 23:25:38

回答

0

首先,在ASP.NET應用程序中,最好使用HttpCache對象,而不是簡單的靜態集合。

對於你的實際問題,你確實可以爲你的集合中的每一個物品保持一個鎖(每個對象在.NET中都有一個監視器,所以它們相對便宜)。不過,你可能希望有對實際徵收的鎖要做到這一點串聯:

我將使用靜態這裏爲了簡單,但正如我上面提到的,HttpCache可能會更好:

class CacheItem 
{ 
    private readonly object _lock = new object(); 

    public void DoSomething() 
    { 
     lock(_lock) 
     { 
      // perform some synchronized action on the individual item 
     } 
    } 
} 

// I'd recommend a reader-writer lock for the 
// collection so that you can have multiple retrievals 
// of items and still lock exclusively for changing the collection 
private static ReaderWriterLockSlim itemsLock = new ReaderWriterLockSlim(); 
private static List<CacheItem> items = new List<CacheItem>(); 

public static void AddItem(CacheItem item) 
{ 
    itemsLock.EnterWriteLock(); 

    try 
    { 
     items.Add(item); 
    } 
    finally 
    { 
     itemsLock.ExitWriteLock(); 
    } 
} 

pulbic static CacheItem GetItem(int index) 
{ 
    itemsLock.EnterReadLock(); 

    try 
    { 
     return items[index]; 
    } 
    finally 
    { 
     itemsLock.ExitReadLock(); 
    } 
} 
3

請參閱Data Structures for Parallel Programming on MSDN,這些比用戶鎖定機制快得多。

在System.Collections.Concurrent命名空間中的集合類提供線程安全的添加和刪除避免鎖儘可能地使用細粒度鎖,其中鎖是必要的操作。

與.NET Framework版本1.0和2.0中引入的集合不同,併發集合類不要求用戶代碼在訪問項目時採取任何鎖定。

+0

我一直在尋找的東西作爲一個-AT-A-時間,非阻塞連接池和您的鏈接指向我正是我需要的:BlockingCollection 默認情況下是圍繞ConcurrentQueue 的包裝。 – madannes 2016-05-12 16:48:29

1

首先,您從不鎖定對象,它是您鎖定的代碼。鎖不會以任何方式保護數據,它只會阻止其他線程輸入相同的代碼。

的對象被用作標識符的鎖,這樣,就可以使用相同的標識符來鎖定幾種方法,或使用不同的標識符鎖定相同的方法。

爲了使鎖適用於這些方法時,他們處理特定的數據,你只需要一個標識符,該數據是唯一的。如果數據是一個對象,您可以簡單地使用該對象本身作爲標識符。

+0

感謝您的澄清 – Sean 2011-03-01 02:10:06