线程安全和带有静态只读数组的 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);
}