我如何重构这个IEnumerable <t>是线程安全的?</t>

时间:2010-04-28 09:20:54

标签: c# thread-safety

我正在看Skeet的AtomicEnumerable,但我不确定如何将它集成到我当前的IEnumerable exmaple(http://msmvps.com/blogs/jon_skeet/archive/2009/10/23/iterating-atomically.aspx

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

感谢

所以...在多个线程上进行操作......给出正确的顺序

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();
    }
}

3 个答案:

答案 0 :(得分:3)

你的意思是你希望每个线程看到相同的序列,或者在所有线程之间,每个项目应该只看一次吗?

你能使用.NET 4吗?如果是这样,Parallel Extensions(例如Parallel.ForEach)就是你的朋友 - 它可能比我想出的任何东西都安全得多:)

编辑:如果你想在每个线程中完全遍历列表,什么都不会修改列表,它将是线程安全的。如果你需要修改列表,那么你应该创建一个列表的副本,然后迭代它。

答案 1 :(得分:1)

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

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

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

您的示例代码原样是线程安全的,但我确信您的真实代码实际上并非如此简单。

答案 2 :(得分:1)

链接的代码解决了一个不同的问题,你正在尝试做一些更困难的事情。只要在迭代时集合没有被修改,你就不必对迭代器做任何特殊处理。保证这一点很困难,你必须保持一个阻止任何线程添加项目的锁。并发性并不好。

如果那不合适,那么您必须复制该集合以提供保证。也没有玫瑰花床,根据定义,线程现在总是会看到该系列的陈旧版本。