如果我有一个包含 100 个项目的列表和 4 个线程,每个线程更改 25 个项目,这样它们就不会更改彼此的项目,那么该列表是否是“线程安全的”,即。它会按预期工作吗?
一个例子是,你有一个包含 1000 只猫的数组,它们的“name”属性是空白的,因为它们没有被命名。您想遍历并命名它们,但您希望它是多线程的。因此,您创建了 10 个线程并告诉每个线程只执行 0-99、100-199 等,然后将它们关闭。
如果我有一个包含 100 个项目的列表和 4 个线程,每个线程更改 25 个项目,这样它们就不会更改彼此的项目,那么该列表是否是“线程安全的”,即。它会按预期工作吗?
一个例子是,你有一个包含 1000 只猫的数组,它们的“name”属性是空白的,因为它们没有被命名。您想遍历并命名它们,但您希望它是多线程的。因此,您创建了 10 个线程并告诉每个线程只执行 0-99、100-199 等,然后将它们关闭。
这会起作用,因为您只是从列表中读取。你不给它写信。
正如其他人已经指出的那样,阅读行为本质上是线程安全的。仅当某些线程想要写入和/或其他线程想要从资源中读取时,并发才会成为问题。
话虽如此,我可以补充一点,如果您为此目的使用集合,则可以考虑使用显式只读集合(或简单地使用 IEnumerable)。.NET 现在提供这些开箱即用的只读集合。这使得您仅从集合中读取更加明确。
附带说明:我不知道您的要求的上下文,也许您只是在这里过度简化了问题,但是对内存中集合的串行访问速度非常快,因此您从集合中读取多个线程只是在以下情况下很有根据:
如果您没有调整列表本身(添加或删除项目)并且您可以保证 4 个线程只使用它们自己的对象,那么从线程同步的角度来看,您会很好
您可以使用并行 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();
}
}
}