多线程和锁定

本文关键字:锁定 多线程 | 更新日期: 2023-09-27 18:34:21

我在多线程主题中有一个问题,如描述

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

假设 ReadEmail 方法持续 10 秒,此时调用 AddEmail。那么会发生任何错误吗?

多线程和锁定

您的ReadEmails方法不是线程安全的。您有几个选择。

选项#1:

您可以在整个foreach环周围放置一个lock

private void ReadEmails()
{
  lock (emails)
  {
    foreach (Email email in this.emails)
    {
      Print(email);
    }
  }
}

选项#2:

您可以在lock内复制列表。然后,您可以无锁定地迭代副本。

private void ReadEmails()
{
  List<Email> copy;
  lock (emails)
  {
    copy = new List<Email>(this.emails);
  }
  foreach (Email email in copy)
  {
    Print(email);
  }
}

您绝对应该在 Read 方法中添加 Lock 方法。 如果不这样做,则有可能在读取过程尚未完成时添加电子邮件。 由于 foreach 方法要求其集合在迭代期间不可更改,因此将引发异常。

 private void ReadEmails()
    {
        lock(emails) {
             foreach (Email email in this.emails) {
                Print(email);
             }
        }
    }