首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >访问单个对象中的字典对象的多个计时器

访问单个对象中的字典对象的多个计时器
EN

Stack Overflow用户
提问于 2012-02-22 09:37:38
回答 2查看 1.2K关注 0票数 0

我有一个单例对象,并在其中定义了一个字典。

代码语言:javascript
运行
复制
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对象。

代码语言:javascript
运行
复制
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上加锁吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 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

票数 5
EN

Stack Overflow用户

发布于 2012-02-22 10:15:48

对于你发布的这个特定的例子,是的,你必须这样做,但严格地说,根据你的使用模式,它并不总是必要的。

例如,如果您预先确定了2个键,那么如果一个线程操作不影响另一个线程操作的状态,则不会修改字典的共享状态。例如,如果您知道您不是在添加/删除键,并且每个线程都将访问特定的键。

让我们考虑下面的简化示例,其中我们只需并行递增2个给定关键字的前一个值:

代码语言:javascript
运行
复制
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万次后,字典中每个键的值会是多少?

好吧,你会得到

代码语言:javascript
运行
复制
Key1 = 10000000
Key2 = 10000000

在上面的示例中,不需要额外的同步,只需将值分配给字典中的现有键。

当然,如果要添加或删除键,则需要考虑同步或使用ConcurrentDictionary<TKey,TValue>等数据结构

在您的示例中,您实际上是在向字典添加值,因此您必须使用某种形式的同步。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9387991

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档