什么是执行一个线程安全的字典的最佳方式? [英] What's the best way of implementing a thread-safe Dictionary?

查看:461
本文介绍了什么是执行一个线程安全的字典的最佳方式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我能够从IDictionary的派生和定义私人SyncRoot上的对象来实现线程安全的词典在C#:<​​/ P>

I was able to implement a thread-safe Dictionary in C# by deriving from IDictionary and defining a private SyncRoot object:

public class SafeDictionary<TKey, TValue>: IDictionary<TKey, TValue>
{
    private readonly object syncRoot = new object();
    private Dictionary<TKey, TValue> d = new Dictionary<TKey, TValue>();

    public object SyncRoot
    {
        get { return syncRoot; }
    } 

    public void Add(TKey key, TValue value)
    {
        lock (syncRoot)
        {
            d.Add(key, value);
        }
    }

    // more IDictionary members...
}

我那么这个SyncRoot上对象在我的消费者锁定(多线程):

I then lock on this SyncRoot object throughout my consumers (multiple threads):

例如:

lock (m_MySharedDictionary.SyncRoot)
{
    m_MySharedDictionary.Add(...);
}

我能够使它发挥作用,但是这导致了一些丑陋的code。我的问题是,有没有执行一个线程安全的词典一个更好,更优雅的方式?

I was able to make it work, but this resulted in some ugly code. My question is, is there a better, more elegant way of implementing a thread-safe Dictionary?

推荐答案

正如彼得说,你可以封装所有的类中的线程安全的。你需要小心任何事件会暴露或添加,确保他们得到外界的任何锁调用。

As Peter said, you can encapsulate all of the thread safety inside the class. You will need to be careful with any events you expose or add, making sure that they get invoked outside of any locks.

public class SafeDictionary<TKey, TValue>: IDictionary<TKey, TValue>
{
    private readonly object syncRoot = new object();
    private Dictionary<TKey, TValue> d = new Dictionary<TKey, TValue>();

    public void Add(TKey key, TValue value)
    {
        lock (syncRoot)
        {
            d.Add(key, value);
        }
        OnItemAdded(EventArgs.Empty);
    }

    public event EventHandler ItemAdded;

    protected virtual void OnItemAdded(EventArgs e)
    {
        EventHandler handler = ItemAdded;
        if (handler != null)
            handler(this, e);
    }

    // more IDictionary members...
}

编辑: MSDN文档指出,枚举在本质上不是线程安全的。这可以是一个原因,露出一个同步对象类的外部。另一种方式来处理,这将是提供一些方法来执行所有成员的行动,并锁定各地成员的枚举。这里的问题是,你如果传递给该功能的操作调用你的字典中的一些成员(这将导致死锁)不知道。揭同步对象允许消费者作出这些决定和不隐藏类中的僵局。

The MSDN docs point out that enumerating is inherently not thread safe. That can be one reason for exposing a synchronization object outside your class. Another way to approach that would be to provide some methods for performing an action on all members and lock around the enumerating of the members. The problem with this is that you don't know if the action passed to that function calls some member of your dictionary (that would result in a deadlock). Exposing the synchronization object allows the consumer to make those decisions and doesn't hide the deadlock inside your class.

这篇关于什么是执行一个线程安全的字典的最佳方式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆