我有一个函数是我的应用程序的主要瓶颈,因为它对线程之间共享的全局列表进行了大量的字符串比较。我的问题基本上是这样的:
在1个函数中多次锁定列表(称为List gList)是不好的。然后再次将其锁定(在执行查找时基本锁定,解锁以准备插入新项目,然后再次锁定并添加新项目)。
当我你是一个探查者时,我没有看到任何迹象表明我为此付出了沉重的代价,但是我可能会在以后的某个时间点,或者当它在野外编码时?在这方面,任何人都有最好的实践或个人经历吗?
答案 0 :(得分:5)
你如何进行锁定?如果情况不是这样,您可能希望使用ReaderWriterLockSlim
。
这是一个简单的用法示例:
class SomeData
{
private IList<string> _someStrings = new List<string>();
private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
public void Add(string text)
{
_lock.EnterWriteLock();
try
{
_someStrings.Add(text);
}
finally
{
_lock.ExitWriteLock();
}
}
public bool Contains(string text)
{
_lock.EnterReadLock();
try
{
return _someStrings.Contains(text);
}
finally
{
_lock.ExitReadLock();
}
}
}
答案 1 :(得分:1)
通常,您希望锁定尽可能短的时间。争用的成本远远高于无争用锁定获取的成本(可以在用户空间中完成),因此即使意味着获取锁定次数。
尽管如此,请确保在适当的情况下对此进行分析:同时负载量很大。否则你的结果与现实没什么关系。
答案 2 :(得分:1)
在我看来,很少有数据可以给出具体答案。通常,锁的数量不会产生性能问题,而是等待该锁的线程数。
答案 3 :(得分:1)
听起来你不想释放查找和插入之间的锁定。要么就是这样,要么在查找期间根本不需要锁定。
您是否仅在元素尚未存在时才尝试添加到列表中?如果是这样,那么在准备元素时,释放两个步骤之间的锁定允许另一个线程添加到列表中。当您准备添加时,您的查找已过期。
如果查找可能已过期不是问题,那么您可能根本不需要在查找期间锁定。