C# 多个计时器访问单例对象中的dictionary对象
我有一个单例对象,其中定义了一个字典C# 多个计时器访问单例对象中的dictionary对象,c#,multithreading,timer,C#,Multithreading,Timer,我有一个单例对象,其中定义了一个字典 public class MyClass { public static readonly MyClass Instance = new MyClass(); private MyClass {} public Dictionary<int, int> MyDictionary = new Dictionary<int, int>(); } 现在我的问题是,考虑到计时器的已用事件处理程序在MyD
public class MyClass
{
public static readonly MyClass Instance = new MyClass();
private MyClass
{}
public Dictionary<int, int> MyDictionary = new Dictionary<int, int>();
}
现在我的问题是,考虑到计时器的已用事件处理程序在MyDictionary的索引1和索引2上唯一地运行,我需要锁定MyDictionary吗?是的,您必须这样做
也就是说阅读是线程安全的,但编辑不是。它还说,迭代字典
是不安全的
如果能够使用.NET 4,则可以使用线程安全的ConcurrentDictionary
是的,你必须这样做
也就是说阅读是线程安全的,但编辑不是。它还说,迭代字典
是不安全的
如果能够使用.NET 4,则可以使用线程安全的ConcurrentDictionary
对于您发布的这个特定示例,是的,您必须这样做,但严格来说,根据您的使用模式,这并不总是必要的 例如,若您有两个预先确定的键,那个么若一个线程操作不影响另一个线程操作的状态,那个么您就不会修改字典的共享状态。例如,如果您知道您没有添加/删除密钥,并且每个线程将访问特定的密钥
让我们考虑下面的简化例子,我们只是简单地递增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();
}
}
在上面的示例中,只需将值分配给字典中的现有键,就不需要额外的同步
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;
}
当然,如果您想添加或移除键,则需要考虑同步或使用数据结构,如<代码> CONTRONTRONGORION < /COD>
在您的例子中,实际上是在向字典中添加值,因此必须使用某种形式的同步 对于您发布的这个特定示例,是的,您必须这样做,但严格来说,根据您的使用模式,这并不总是必要的 例如,若您有两个预先确定的键,那个么若一个线程操作不影响另一个线程操作的状态,那个么您就不会修改字典的共享状态。例如,如果您知道您没有添加/删除密钥,并且每个线程将访问特定的密钥
让我们考虑下面的简化例子,我们只是简单地递增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();
}
}
在上面的示例中,只需将值分配给字典中的现有键,就不需要额外的同步
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;
}
当然,如果您想添加或移除键,则需要考虑同步或使用数据结构,如<代码> CONTRONTRONGORION < /COD>
在您的例子中,实际上是在向字典中添加值,因此必须使用某种形式的同步 好极了。我喜欢这本词典。非常感谢,太好了。我喜欢这本词典。非常感谢。