关于使用ConcurrentDictionary的一些问题

ama*_*eur 10 c# asp.net multithreading thread-safety concurrentdictionary

我目前正在编写一个C#应用程序.我是使用ConcurrentDictionary的新手,因此对其线程安全性有一些疑问.首先,这是我的字典:

    /// <summary>
    /// A dictionary of all the tasks scheduled
    /// </summary>
    private ConcurrentDictionary<string, ITask> tasks;
Run Code Online (Sandbox Code Playgroud)

我在我的类中实例化它并使用它来跟踪实现ITask的所有对象.我想确保我的设置在多线程环境中正常工作.

如果多个线程想要获取ConcurrentDictionary中项目数的计数,我是否需要锁定它?

如果我想从字典中获取特定键,获取该键的对象并在其上调用方法,是否需要锁定它?例如:

    /// <summary>
    /// Runs a specific task.
    /// </summary>
    /// <param name="name">Task name.</param>
    public void Run(string name)
    {
        lock (this.syncObject)
        {
            var task = this.tasks[name] as ITask;
            if (task != null)
            {
                task.Execute();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

保持多个线程可以调用Run方法来调用ITask的Execute方法.我的目标是让一切线程安全且尽可能高效.

yam*_*men 9

它们的方法和属性ConcurrentDictionary完全是线程安全的:

http://msdn.microsoft.com/en-us/library/dd287191.aspx

表示可以由多个线程同时访问的键值对的线程安全集合.

这包括Count属性:

Count具有快照语义,表示访问Count时ConcurrentDictionary中的项目数.

然而这并不能意味着字典里举行的对象本身是线程安全的.也就是说,没有什么能阻止两个线程访问同一个Task对象并尝试Execute在其上运行该方法.如果您希望序列化(锁定)访问该Execute方法的每个单独任务,那么我建议在内部使用锁定对象Task并在运行时锁定Execute:

public class Task
{
    private object _locker = new object();

    public void Execute()
    {
        lock (_locker) {
           // code here
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这可确保至少每个单独的任务都没有运行多个线程Execute.我猜这是你在问题的上下文和类和方法的名称之后所做的.