线程和对共享列表的访问
Posted
技术标签:
【中文标题】线程和对共享列表的访问【英文标题】:Threads and access to a shared list 【发布时间】:2017-12-10 18:17:18 【问题描述】:我正在尝试编写的 WCF 服务遇到(我希望)一个死锁问题。
我对“定位”列表中的特定项目的函数有以下锁定:
CIPRecipe FindRecipe_ByUniqueID(string uniqueID)
lock (_locks[LOCK_RECIPES])
foreach (var r in _recipes.Keys)
if (_recipes[r].UniqueID == uniqueID)
return _recipes[r];
return null;
但是,各种函数通过这个列表重复,并且总是应用相同的 LOCK,例如 ....
lock (_locks[LOCK_RECIPES_NO_ADD_OR_REMOVE])
foreach (var r in _recipes)
r.Value.UpdateSummary();
summaries.Add((RecipeSummary)r.Value.Summary);
我怀疑的是,上面示例中的 _recipes 中的一个项目突然调用了一个函数,该函数最终调用了第一个函数 - “CIPRecipe FindRecipe_ByUniqueID(string uniqueID)”,这会在迭代中达到它时导致死锁。
我需要在迭代时停止更改此列表。有人可以告诉我最佳做法吗?
谢谢
【问题讨论】:
你应该关注ReaderWriterLockSlim
谢谢,请将您的评论升级为答案,我会接受。不知道为什么这个问题收到了反对票...
【参考方案1】:
你想要的是使用ReaderWriterLockSlim
,这将允许无限的并发读者通过但只有一个作家通过并在作家写作时阻止所有读者。
这假设 _locks
已从 object[]
更改为 ReaderWriterSlim[]
//On Read
CIPRecipe FindRecipe_ByUniqueID(string uniqueID)
var lockObj = _locks[LOCK_RECIPES];
lockObj.EnterReadLock();
try
foreach (var r in _recipes.Keys)
if (_recipes[r].UniqueID == uniqueID)
return _recipes[r];
finally
lockObj.ExitReadLock();
return null;
//On write
var lockObject = _locks[LOCK_RECIPES]; //Note this now uses the same lock object as the other method.
lockObj.EnterWriteLock();
try
foreach (var r in _recipes)
r.Value.UpdateSummary();
summaries.Add((RecipeSummary)r.Value.Summary);
finally
lockObj.ExitWriteLock();
我不知道它是否会解决您的死锁问题,如果它是由于您在写入期间允许读取引起的。
【讨论】:
感谢您,虽然我使用了 TryEnterWriteLock、TryEnterReadLock 作为附加检查,但仅使用“lock (lockObject)”是更好的解决方案。【参考方案2】:也许这里调用了 ConcurrentDictionary?
【讨论】:
Thanjs Hugh,我不知道这个课程,但它非常适合我的需要。以上是关于线程和对共享列表的访问的主要内容,如果未能解决你的问题,请参考以下文章