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

发布于 2025-01-07 16:11:04 字数 1047 浏览 0 评论 0原文

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

public class MyClass 
{
    public static readonly MyClass Instance = new MyClass();

    private MyClass
    {}

    public Dictionary<int, int> MyDictionary = new Dictionary<int, int>();
}

现在,我有两个 System.Timers.Timer 对象更新 MyDictionary。

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 进行锁定?

I have a singleton object and have a dictionary defined in it.

public class MyClass 
{
    public static readonly MyClass Instance = new MyClass();

    private MyClass
    {}

    public Dictionary<int, int> MyDictionary = new Dictionary<int, int>();
}

Now, I have two System.Timers.Timer objects updating MyDictionary.

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;
}

My question is now, considering the elapsed event handler of timers operate uniquely on index 1 and index 2 of MyDictionary, do I need any lock on MyDictionary ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半﹌身腐败 2025-01-14 16:11:04

是的,你必须这样做。

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

这表示读取是线程安全的,但编辑不是。它还表示迭代 Dictionary 并不真正安全。

如果您能够使用 .NET 4,则可以使用线程安全的 ConcurrentDictionary

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

Yes, you have to.

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

That says reading is thread safe, but editing is not. It also says it isn't really safe to iterate the Dictionary.

If you are able to use .NET 4, you can use a ConcurrentDictionary, which is thread safe.

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

永言不败 2025-01-14 16:11:04

对于您发布的这个具体示例,是的,您必须这样做,但严格来说,根据您的使用模式,这并不总是必要的。

例如,如果您预先确定了 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();
    }
}

您认为在 2 个单独线程中迭代后字典的每个键的值会是多少在循环内同时使用同一字典超过 1000 万次?

在上面的示例中,您

Key1 = 10000000
Key2 = 10000000

不需要额外的同步,只需将值分配给字典中的现有键即可。

当然,如果您想添加或删除键那么您需要考虑同步或使用数据结构,例如ConcurrentDictionary

在您的情况下,您实际上是在添加值到字典中,因此您必须使用某种形式的同步。

For this specific example that you post, yes you have to, but strictly speaking, it is not always necessary depending on your usage pattern.

For example, If you have 2 keys predetermined, then you are not modifying shared state of the dictionary if one thread operation is not affecting state of the other thread operation. For example, if you know that you are not adding/removing keys and that each thread will be accessing a specific key.

Lets consider the following simplified example where we are simply incrementing the previous value of 2 given keys in parallel:

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();
    }
}

What do you think the value of each of the keys of the dictionary will be after iterating in 2 separate threads simultaneously on the same dictionary for more than 10 million times within a loop?

Well you get

Key1 = 10000000
Key2 = 10000000

No extra synchronization is necessary in the above example simply to assign values to existing keys in a dictionary.

Of course, if you wanted to add or remove keys then you need to consider synchronizing or using data structures such as ConcurrentDictionary<TKey,TValue>

In your case you are actually adding values to the dictionary, so you have to use some form of synchronization.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文