我有一个静态的对象集合,它们会经常从多个线程更新。是否可以锁定集合中的单个对象而不是锁定整个集合,以便只有试图访问集合中同一对象的线程才会被阻塞而不是每个线程?
如果有更好的方法可以从多个线程更新集合中的对象,我会全力以赴。
答案 0 :(得分:3)
参考Data Structures for Parallel Programming on MSDN,这些明显快于用户锁定机制。
System.Collections.Concurrent命名空间中的集合类提供了线程安全的添加和删除操作,可以尽可能避免锁定,并在需要锁定时使用细粒度锁定。
与.NET Framework 1.0和2.0版中引入的集合不同,并发集合类在访问项目时不需要用户代码来获取任何锁定。
答案 1 :(得分:1)
首先,在ASP.NET应用程序中,最好使用HttpCache对象,而不是简单的静态集合。
根据您的实际问题,您确实可以为集合中的每个项目维护一个锁(每个对象在.NET中都有一个监视器,因此它们相对便宜)。但是,您可能希望与实际集合锁定一起执行此操作:
为了简单起见,我将在这里使用static,但正如我上面提到的,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();
}
}
答案 2 :(得分:1)
首先,你永远不会锁定一个对象,它是你锁定的代码。锁不会以任何方式保护数据,它只会阻止其他线程输入相同的代码。
对象用作锁的标识符,这样您就可以使用相同的标识符来锁定多个方法,或者使用不同的标识符锁定相同的方法。
要使锁在处理特定数据时应用于方法,您只需要一个对该数据唯一的标识符。如果数据是对象,则可以简单地将对象本身用作标识符。