是列表<;T>;如果只是更改值,则线程安全
本文关键字:安全 线程 如果 lt 列表 gt | 更新日期: 2023-09-27 18:23:38
如果我有一个包含100个项目的列表,以及4个线程,每个线程更改25个项目,这样它们就不会更改彼此的项目,那么这个列表会是"线程安全的"吗?也就是说,它会按预期工作吗?
举个例子,你有一个1000只猫的数组,它们的"name"属性为空,因为它们还没有被命名。您希望遍历并命名所有这些,但希望它是多线程的。因此,您创建了10个线程,并告诉每个线程只执行0-99、100-199等操作,然后将它们设置为关闭状态
这会起作用,因为您只是从列表中读取。你不写。
话虽如此,我可以补充一点,如果您为此目的使用集合,则可以考虑使用显式只读集合(或简单地使用IEnumerable)。NET现在提供了这些开箱即用的只读集合。这样可以更明确地表明,您只是在阅读该集合。
顺便说一句:我不知道你的需求的上下文,也许你只是过于简化了这里的问题,但对内存中集合的串行访问速度非常快,所以只有在以下情况下,从集合中读取多个线程才是有根据的:
- 您不是从内存读取,而是从磁盘读取(I/O很慢)
- 您正在执行的操作对象的操作很慢(就像毫秒或更大的数量级,而不是简单的属性修改)
如果您没有对列表本身进行中间化(添加或删除项目),并且您可以确保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();
}
}
}