1

コレクションを反復処理し、アイテムを追加し、異なるスレッドから同時にすべてのアイテムを削除できるようにするための最良の方法を見つけようとしています。パフォーマンスはイテレーション コンポーネントにとって重要ですが、項目の追加と削除はあまり頻繁に行われないため、追加/削除のパフォーマンスはそれほど重要ではありません。

これが私が思いついたものです:

public class AtomicList<T> : IEnumerable<T>
{
    private readonly object Locker = new object();
    private List<T> InternalCollection = new List<T>();

    public void Add(T Value)
    {
        lock (Locker)
        {
            List<T> Update = new List<T>(InternalCollection);
            Update.Add(Value);
            InternalCollection = Update;
        }
    }

    public void Remove(T Value)
    {
        lock (Locker)
        {
            List<T> Update = new List<T>(InternalCollection);
            Update.Remove(Value);
            InternalCollection = Update;
        }
    }

    public IEnumerator<T> GetEnumerator()
    {
        return InternalCollection.GetEnumerator();
    }

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

このようにすることの欠点はありますか?上記で説明したように、これがスレッドセーフ/反復可能ではない状況はありますか?

また、foreach と IEnumerable を使用するとパフォーマンス コストがかかりますか? InternalCollection に直接アクセスして for ステートメントを実行した方がよいでしょうか?

4

1 に答える 1

3

AddメソッドとRemoveメソッドを同時に呼び出さない場合は、フィールドlockによって参照されるリストからのみ読み取るため、sは必要ありません。Interlocked.ExchangeメソッドInternalCollectionを使用して、スレッドセーフな方法で古いリストを新しいリストに置き換えます。

public class AtomicList<T> : IEnumerable<T>
{
    private List<T> internalCollection = new List<T>();

    public void Add(T vlue)
    {
        List<T> update = new List<T>(internalCollection);
        update.Add(value);
        Interlocked.Exchange(ref internalCollection, update);
    }

    public bool Remove(T value)
    {
        List<T> update = new List<T>(internalCollection);
        bool removed = update.Remove(value);
        if (removed) Interlocked.Exchange(ref internalCollection, update);
        return removed;
    }

    public IEnumerator<T> GetEnumerator()
    {
        ...
于 2012-06-18T15:03:36.903 に答える