- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
根据我的理解,给定一个 C# 数组,从多个线程并发迭代数组的行为是线程安全操作。
通过迭代数组我的意思是通过普通的旧for
读取数组内的所有位置。循环。每个线程只是读取数组内内存位置的内容,没有人写入任何内容,因此所有线程都以一致的方式读取相同的内容。
这是一段执行我上面编写的代码:
public class UselessService
{
private static readonly string[] Names = new [] { "bob", "alice" };
public List<int> DoSomethingUseless()
{
var temp = new List<int>();
for (int i = 0; i < Names.Length; i++)
{
temp.Add(Names[i].Length * 2);
}
return temp;
}
}
所以,我的理解是方法DoSomethingUseless
线程安全并且无需替换 string[]
具有线程安全类型(例如 ImmutableArray<string>
)。
我说得对吗?
现在假设我们有一个 IEnumerable<T>
的实例。我们不知道底层对象是什么,我们只知道我们有一个实现 IEnumerable<T>
的对象,因此我们可以使用 foreach
对其进行迭代环形。
根据我的理解,在这种情况下,无法保证从多个线程并发迭代此对象是线程安全操作。换句话说,完全有可能迭代 IEnumerable<T>
来自不同线程的实例同时破坏了对象的内部状态,从而使其损坏。
我在这一点上正确吗?
IEnumerable<T>
怎么样?实现Array
类(class) ?它是线程安全的吗?
换句话来说,下面的代码线程安全吗? (这与上面的代码完全相同,但现在使用 foreach
循环而不是 for
循环来迭代数组)
public class UselessService
{
private static readonly string[] Names = new [] { "bob", "alice" };
public List<int> DoSomethingUseless()
{
var temp = new List<int>();
foreach (var name in Names)
{
temp.Add(name.Length * 2);
}
return temp;
}
}
是否有任何引用说明 IEnumerable<T>
.NET 基类库中的实现是实际上线程安全吗?
最佳答案
在 C# 中使用 for 循环迭代数组是线程安全操作吗?
如果您严格谈论从多个线程读取,那么对于 Array
来说这将是线程安全的。和List<T>
以及 Microsoft 编写的几乎所有集合,无论您是否使用 for
或foreach
环形。特别是在您的示例中:
var temp = new List<int>();
foreach (var name in Names)
{
temp.Add(name.Length * 2);
}
您可以根据需要跨多个线程执行此操作。他们都会从 Names
读取相同的值。很高兴。
如果您从另一个线程写入(这不是您的问题,但值得注意)
迭代Array
或List<T>
与 for
循环,它会继续读取,并且当您遇到更改的值时它会很乐意读取它们。
使用 foreach
进行迭代循环,那么这取决于实现。如果 Array
中的值通过 foreach
进行部分更改循环,它只会继续枚举并为您提供更改后的值。
与 List<T>
,这取决于您认为“线程安全”。如果您更关心读取准确的数据,那么它有点“安全”,因为它会在枚举中抛出异常并告诉您集合已更改。但如果您认为抛出异常不安全,那么它也不安全。
但值得注意的是,这是 List<T>
中的设计决策, there is code显式查找更改并引发异常。设计决策将我们引向下一点:
我们能否假设每个实现 IEnumerable
的集合跨多个线程读取是否安全?
在大多数情况下都会如此,但不能保证线程安全的读取。原因是因为每IEnumerable
需要执行 IEnumerator
,它决定如何遍历集合中的项目。就像任何类一样,您可以在其中执行任何您想要的操作,包括非线程安全的操作,例如:
你甚至可以做一些奇怪的事情,比如 make GetEnumerator()
每次调用时都会返回枚举器的相同实例。这确实可能会产生一些不可预测的结果。
如果某些东西会导致不可预测的结果,我认为它不是线程安全的。任何这些事情都可能导致不可预测的结果。
您可以看到the source code for the Enumerator
that List<T>
uses ,所以你可以看到它没有做任何奇怪的事情,这告诉你枚举 List<T>
来自多个线程是安全的。
关于c# - 在 C# 中,使用 for 循环迭代数组是线程安全操作吗?使用 foreach 循环迭代 IEnumerable<T> 怎么样?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58867108/
我是一名优秀的程序员,十分优秀!