线程安全和带有静态只读数组的 foreach
Threadsafety and foreach with static readonly arrays
我有几个类型为 'static readonly' 的 char[] 和 string[] 数组。他们的项目永远不会改变。
'foreach' 和 'generics' 枚举是线程安全的吗?
private static readonly string[] staticReadOnlyArray = new string[] { "someKey0", "someKey1", "someKey2", ... };
public bool SomeThreadSharedCall(string toCheck)
{
// #1
foreach (string s in staticReadOnlyArray)
{
if (s == toCheck)
return true;
}
return false;
// #2
return staticReadOnlyArray.Contains(toCheck);
// or #3
return staticReadOnlyArray.Any(s => string.Compare(toCheck, s, StringComparison.OrdinalIgnoreCase) == 0);
// or #4
staticReadOnlyArray.ForEach(s => someAction(s, toCheck));
}
如果您不确定,最好的方法就是测试一下!但是,是的,它们是线程安全的。
您的方法中的操作 "threadsafe" 仅基于您的声明 Their items never change.
;但是,给定代码中的任何内容都不能保证这一点。
术语 threadsafe 通常用于表示所讨论的代码 保证 数据不会更改,或者如果它 可以改变,运行仍会产生正确的结果。
您需要执行 your own synchronization logic 才能使代码真正线程安全。
=== 回复您的评论:
GetEnumerator() 的 return 值——你调用的 iterator
——本身对于调用线程独占使用是安全的,但这不是这里的问题。它是非线程安全的底层集合(数组),因为它可以更改。
将 foreach
更改为 for
循环不会使代码线程安全。您需要同步对集合的访问,或者使其不可变。
在你的情况下,我建议后者,因为你的数组中的数据是常量。为了让您更具体,这里有一些概念性代码:
private static readonly IEnumerable<string> staticReadOnlyData = Array.AsReadOnly( new string[] { "someKey0", "someKey1", "someKey2", ... } );
public bool SomeThreadSharedCall(string toCheck)
{
// #1
foreach (string s in staticReadOnlyData)
{
if (s == toCheck)
return true;
}
return false;
// #2
return staticReadOnlyData.Contains(toCheck);
// or #3
return staticReadOnlyData.Any(s => string.Compare(toCheck, s, StringComparison.OrdinalIgnoreCase) == 0);
}
我有几个类型为 'static readonly' 的 char[] 和 string[] 数组。他们的项目永远不会改变。
'foreach' 和 'generics' 枚举是线程安全的吗?
private static readonly string[] staticReadOnlyArray = new string[] { "someKey0", "someKey1", "someKey2", ... };
public bool SomeThreadSharedCall(string toCheck)
{
// #1
foreach (string s in staticReadOnlyArray)
{
if (s == toCheck)
return true;
}
return false;
// #2
return staticReadOnlyArray.Contains(toCheck);
// or #3
return staticReadOnlyArray.Any(s => string.Compare(toCheck, s, StringComparison.OrdinalIgnoreCase) == 0);
// or #4
staticReadOnlyArray.ForEach(s => someAction(s, toCheck));
}
如果您不确定,最好的方法就是测试一下!但是,是的,它们是线程安全的。
您的方法中的操作 "threadsafe" 仅基于您的声明 Their items never change.
;但是,给定代码中的任何内容都不能保证这一点。
术语 threadsafe 通常用于表示所讨论的代码 保证 数据不会更改,或者如果它 可以改变,运行仍会产生正确的结果。
您需要执行 your own synchronization logic 才能使代码真正线程安全。
=== 回复您的评论:
GetEnumerator() 的 return 值——你调用的 iterator
——本身对于调用线程独占使用是安全的,但这不是这里的问题。它是非线程安全的底层集合(数组),因为它可以更改。
将 foreach
更改为 for
循环不会使代码线程安全。您需要同步对集合的访问,或者使其不可变。
在你的情况下,我建议后者,因为你的数组中的数据是常量。为了让您更具体,这里有一些概念性代码:
private static readonly IEnumerable<string> staticReadOnlyData = Array.AsReadOnly( new string[] { "someKey0", "someKey1", "someKey2", ... } );
public bool SomeThreadSharedCall(string toCheck)
{
// #1
foreach (string s in staticReadOnlyData)
{
if (s == toCheck)
return true;
}
return false;
// #2
return staticReadOnlyData.Contains(toCheck);
// or #3
return staticReadOnlyData.Any(s => string.Compare(toCheck, s, StringComparison.OrdinalIgnoreCase) == 0);
}