ConcurrentDictionary和线程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ConcurrentDictionary和线程相关的知识,希望对你有一定的参考价值。

我在IIS应用程序池中有一个WCF服务。 WCF服务的方法接收JSON中的一些数据,如{“object”:“someobject”,“payload”:[int key]}。 对于每个请求,我运行新线程来使用密钥。 关键是添加到ConcurrentDictionary并锁定ConcurrentDictionary的值。 这样做的目的是:只有一个密钥可以运行一次,例如: 线程1 - 使用键1运行 线程2 - 使用键2运行 线程3 - 线程1中的等待锁定 但是当我从ConcurrentDictionary中删除键时,另一个线程已经通过键获取值并使用它。怎么避免这个?附近的线程处理程序示例

static ConcurrentDictionary<string, object> taskDictionary=new ConcurrentDictionary<string, object>();
static void ThreadHandler(int key)
        {   
            try
            {
                var  lockElem=taskDictionary.GetOrAdd(key, new object());
//Thread 3 get value by key 1 here and waits here
                lock(lockElem)
                {
                    taskDictionary.TryRemove(key, out _);
// but Thread 1 removes value by key 1 here
//and Thread 4 can add value in Dictionary with same key (key 1)
                }
            }
            finally
            {
            }
        }

在这种情况下出现问题:线程1使用GetOrAdd,然后使用锁定值,然后使用TryRemove。在这个时候,线程3.使用GetOrAdd,取值,但是等待来自线程1的锁定。当线程1的锁定释放时,线程3锁定删除了值。在这个时候,线程4使用GetOrAdd,并创建新的字典元素(与线程3采用的值不匹配)。我们有2个线程(线程3和线程4)使用相同的密钥。

答案

如果字典中不存在,TryRemove函数已经为您提供了一个默认对象,因此您可以简单地执行以下操作:

static ConcurrentDictionary<int, object> taskDictionary=new ConcurrentDictionary<int, object>();
static void ThreadHandler(int key)
{   
    try
    {
        object obj;

        // Remove object with key = 'key', or create a new object if it does not yet exist
        taskDictionary.TryRemove(key, out obj);

        // Do whatever you need to do with 'obj'

        // Add the object (back) to the dictionary if necessary
        taskDictionary.GetOrAdd(key, obj);
    }
    finally
    {
    }
}

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

ConcurrentDictionary 与 Dictionary

ConcurrentDictionary线程不安全么,你难道没疑惑,你难道弄懂了么?

ConcurrentDictionary线程不安全么,你难道没疑惑,你难道弄懂了么?

ConcurrentDictionary和Dictionary对比

如何证明 ConcurrentDictionary 字典操作"不全是"线程安全的

C# 中 ConcurrentDictionary 一定线程安全吗?