3

如果我有一个包含 100 个项目的列表和 4 个线程,每个线程更改 25 个项目,这样它们就不会更改彼此的项目,那么该列表是否是“线程安全的”,即。它会按预期工作吗?

一个例子是,你有一个包含 1000 只猫的数组,它们的“name”属性是空白的,因为它们没有被命名。您想遍历并命名它们,但您希望它是多线程的。因此,您创建了 10 个线程并告诉每个线程只执行 0-99、100-199 等,然后将它们关闭。

4

4 回答 4

2

这会起作用,因为您只是从列表中读取。你不给它写信。

于 2013-07-17T10:52:14.323 回答
2

正如其他人已经指出的那样,阅读行为本质上是线程安全的。仅当某些线程想要写入和/或其他线程想要从资源中读取时,并发才会成为问题。

话虽如此,我可以补充一点,如果您为此目的使用集合,则可以考虑使用显式只读集合(或简单地使用 IEnumerable)。.NET 现在提供这些开箱即用的只读集合。这使得您仅从集合中读取更加明确。

附带说明:我不知道您的要求的上下文,也许您只是在这里过度简化了问题,但是对内存中集合的串行访问速度非常快,因此您从集合中读取多个线程只是在以下情况下很有根据:

  • 您不是从内存读取,而是从磁盘读取(I/O 很慢)
  • 您为操作对象而执行的操作很慢(例如毫秒或更长,而不是简单的属性修改)
于 2013-07-17T11:18:35.443 回答
1

如果您没有调整列表本身(添加或删除项目)并且您可以保证 4 个线程只使用它们自己的对象,那么从线程同步的角度来看,您会很好

于 2013-07-17T10:54:47.157 回答
0

您可以使用并行 linq 功能而不是一些自制线程:

namespace CSharp
{
  using System;
  using System.Collections.Generic;
  using System.Linq;

  class Cat
  {
    public string Name { get; set; }
  }

  class Program
  {
    private static void Main()
    {
      var cats = new List<Cat>();

      for (int i = 0; i < 100; ++i)
      {
        cats.Add(new Cat());
      }

      cats.AsParallel().ForAll(cat => cat.Name = "Carlo");

      foreach (var cat in cats)
      {
        Console.WriteLine(cat.Name);
      }

      Console.ReadLine();
    }
  }
}
于 2013-07-17T11:03:48.657 回答