C# 多线程和锁
我有一个关于多线程的问题C# 多线程和锁,c#,multithreading,collections,C#,Multithreading,Collections,我有一个关于多线程的问题 private List<Email> emails = new List<Email>(); private void AddEmail(Email email) { lock (this.emails) { this.emails.Add(email); } } private void ReadEmails() {
private List<Email> emails = new List<Email>();
private void AddEmail(Email email)
{
lock (this.emails)
{
this.emails.Add(email);
}
}
private void ReadEmails()
{
foreach (Email email in this.emails)
{
Print(email);
}
}
private List emails=new List();
私人邮件(电子邮件)
{
锁(这个。电子邮件)
{
这个.email.Add(email);
}
}
私有无效读邮件()
{
foreach(此.emails中的电子邮件)
{
打印(电子邮件);
}
}
假设ReadEmails方法持续10秒,此时调用AddEmail。那么会发生错误吗?您肯定应该在Read方法中添加Lock方法。如果不这样做,则可能会在阅读过程尚未完成时添加电子邮件。由于foreach方法要求其集合在迭代期间不可更改,因此将引发异常
private void ReadEmails()
{
lock(emails) {
foreach (Email email in this.emails) {
Print(email);
}
}
}
您的
ReadEmails
方法不是线程安全的。你有两个选择
选项#1:
您可以在整个foreach
循环周围放置锁
private void ReadEmails()
{
lock (emails)
{
foreach (Email email in this.emails)
{
Print(email);
}
}
}
选项2:
您可以在锁中复制列表。然后您可以无锁地迭代复制
private void ReadEmails()
{
List<Email> copy;
lock (emails)
{
copy = new List<Email>(this.emails);
}
foreach (Email email in copy)
{
Print(email);
}
}
private void ReadEmails()
{
清单副本;
锁定(电子邮件)
{
复制=新列表(此为.email);
}
foreach(电子邮件副本)
{
打印(电子邮件);
}
}
如果不告诉我们这应该是什么语言,就不可能回答这个问题——所发生的事情完全取决于实现。+1不过,有一点建议@Bac,最佳做法是使用不同的对象进行锁定,如私有只读对象_locker=new object()编码>并锁定该对象…公平地说,电子邮件
已经声明为私有,因此在这种情况下使用不同的对象不会为您带来很多好处。