线程和对共享列表的访问

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,我不知道这个课程,但它非常适合我的需要。

以上是关于线程和对共享列表的访问的主要内容,如果未能解决你的问题,请参考以下文章

进程和线程之间共享和更新列表

两个线程之间的列表共享

主线程退出后线程访问共享变量

跨线程共享内存访问

多线程访问共享对象和数据的方式

多线程篇五:多个线程访问共享对象和数据的方式