我有一个单例对象,并在其中定义了一个字典。
public class MyClass 
{
    public static readonly MyClass Instance = new MyClass();
    private MyClass
    {}
    public Dictionary<int, int> MyDictionary = new Dictionary<int, int>();
}现在,我有两个更新MyDictionary的System.Timers.Timer对象。
System.Timers.Timer timer1 = new System.Timers.Timer(5);
timer1.AutoReset = false;
timer1.Elapsed += new System.Timers.ElapsedEventHandler(MyTimer1Handler);
timer1.Enabled = true;
timer1.Start();
System.Timers.Timer timer2 = new System.Timers.Timer(5);
timer2.AutoReset = false;
timer2.Elapsed += new System.Timers.ElapsedEventHandler(MyTimer2Handler);
timer2.Enabled = true;
timer2.Start();
private void MyTimer1Handler(object sender, ElapsedEventArgs e)
{
     MyClass.Instance.MyDictonary[1] = 100;
}
private void MyTimer1Handler(object sender, ElapsedEventArgs e)
{
     MyClass.Instance.MyDictonary[2] = 100;
}我的问题是,考虑到计时器的耗时事件处理程序在MyDictionary的索引1和索引2上唯一地操作,我需要在MyDictionary上加锁吗?
发布于 2012-02-22 09:45:20
是的,你必须这样做。
http://msdn.microsoft.com/en-us/library/xfhwa508.aspx
这说明读取是线程安全的,但编辑不是。它还说,迭代Dictionary是不安全的。
如果您能够使用.NET 4,则可以使用线程安全的ConcurrentDictionary。
http://msdn.microsoft.com/en-us/library/dd287191.aspx
发布于 2012-02-22 10:15:48
对于你发布的这个特定的例子,是的,你必须这样做,但严格地说,根据你的使用模式,它并不总是必要的。
例如,如果您预先确定了2个键,那么如果一个线程操作不影响另一个线程操作的状态,则不会修改字典的共享状态。例如,如果您知道您不是在添加/删除键,并且每个线程都将访问特定的键。
让我们考虑下面的简化示例,其中我们只需并行递增2个给定关键字的前一个值:
class Program
{
    static Dictionary<string, int> _dictionary = new Dictionary<string, int>();
    static void Main(string[] args)
    {
        _dictionary["key1"] = 0;
        _dictionary["key2"] = 0;
        Action<string> updateEntry = (key) =>
            {
                for (int i = 0; i < 10000000; i++)
                {
                    _dictionary[key] = _dictionary[key] + 1;
                }
            };
        var task1 = Task.Factory.StartNew(() =>
            {
                updateEntry("key1");
            });
        var task2 = Task.Factory.StartNew(() =>
        {
            updateEntry("key2");
        });
        Task.WaitAll(task1, task2);
        Console.WriteLine("Key1 = {0}", _dictionary["key1"]);
        Console.WriteLine("Key2 = {0}", _dictionary["key2"]);
        Console.ReadKey();
    }
}你认为在同一个字典上同时在两个单独的线程中迭代超过1000万次后,字典中每个键的值会是多少?
好吧,你会得到
Key1 = 10000000
Key2 = 10000000在上面的示例中,不需要额外的同步,只需将值分配给字典中的现有键。
当然,如果要添加或删除键,则需要考虑同步或使用ConcurrentDictionary<TKey,TValue>等数据结构
在您的示例中,您实际上是在向字典添加值,因此您必须使用某种形式的同步。
https://stackoverflow.com/questions/9387991
复制相似问题