【问题标题】:How do I refactor this IEnumerable<T> to be thread-safe?如何将此 IEnumerable<T> 重构为线程安全的?
【发布时间】:2010-04-28 09:20:54
【问题描述】:

我正在查看 Skeet 的 AtomicEnumerable,但我不确定如何将其集成到下面的当前 IEnumerable 示例中 (http://msmvps.com/blogs/jon_skeet/archive/2009/10/23/iterating-atomically.aspx)

基本上我想以线程安全的方式 foreach 我的 blahs 类型。

谢谢

所以 .. foreach 在多个线程上...给出正确的顺序

Blahs b = new Blahs();

foreach(b 中的字符串 s) { }

public sealed class Blahs :  IEnumerable<string>
{
    private readonly IList<string> _data = new List<string>() { "blah1", "blah2", "blah3" };

    public IEnumerator<string> GetEnumerator()
    {
        return _data.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

【问题讨论】:

    标签: c# thread-safety


    【解决方案1】:

    你的意思是你想让每个线程看到相同的序列,还是在所有线程之间,每个项目应该只看到一次?

    您可以使用 .NET 4 吗?如果是这样,并行扩展(例如Parallel.ForEach)是你的朋友——它可能比我想出的任何东西都安全:)

    编辑:如果您只想在每个线程中完全迭代列表,并且不会修改列表,它已经是线程安全的。如果您确实需要修改列表,那么您应该创建列表的副本并对其进行迭代。

    【讨论】:

    • 我需要每个线程看到相同的序列。不幸的是,我暂时停留在 3.5 上
    【解决方案2】:

    如果您只需要每个线程看到相同的序列,那么您的代码可能是线程安全的。

    您的_data 列表是私有的,因此只能在Blahs 类本身内进行修改(假设您没有在其他地方公开它)。

    List&lt;T&gt; 类对于多个并发读取器是安全的,这意味着您需要做的就是确保您的 Blahs 类在枚举时不会修改集合。

    您的示例代码本身是线程安全的,但我敢肯定您的真实代码实际上并非如此简单。

    【讨论】:

      【解决方案3】:

      链接的代码解决了一个不同的问题,您正在尝试做一些更困难的事情。您不必对迭代器做任何特别的事情,只要 在迭代时集合没有被修改。保证这一点可能很困难,您必须保持锁定以防止任何线程添加项目。不适合并发。

      如果这不合适,那么您必须制作该系列的副本以提供保证。也没有任何好处,一个线程现在根据定义总是会看到该集合的陈旧版本。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-30
        • 2012-01-26
        • 1970-01-01
        • 1970-01-01
        • 2011-09-30
        • 1970-01-01
        相关资源
        最近更新 更多