5

私はスレッド初心者で、C# (.NET 3.5 SP1) でカスタム スレッド セーフ ジェネリック リスト クラスを作成しようとしています。私は読んだことがありますなぜスレッドセーフなコレクションはとても難しいのですか? . クラスの要件を確認した後、リストに安全に追加してリストを返すだけでよいと思います。この例は、リターンリストメソッドがないことを除いて、私が望むほとんどすべてを示しているため、以下のように独自のパブリックメソッドを作成しました:

更新:提案に基づいて、要件を確認したため、クラスを以下のように単純化しました。

public sealed class ThreadSafeList<T>
{
    private readonly IList<T> list = new List<T>();
    private readonly object lockable = new object();

    public void Add(T t)
    {
        lock (lockable)
        {
            list.Add(t);
        }
    }

    public IList<T> GetSnapshot()
    {
        IList<T> result;
        lock (lockable)
        {
            result = new List<T>(list);
        }
        return result;
    }
}
4

4 に答える 4

2

@jrista に同意します。解決する必要があるセマンティクスの問題がありますが、なぜそれが呼び出されるのTranslate()ですか? 意図は何ですか?

A - 現在のコード - 内部リストの読み取り専用ラッパーを返します

return new ReadOnlyCollection<T>(list);

別のスレッドがリストを反復処理している場合に元のリストが変更された場合、スレッドの問題は引き続き発生します。このことを認識している限り、それは大きな問題ではありません。

B - 読み取り専用コピー。

return new List<T>(list).AsReadOnly();

新しいリストは何も変更されないため、このリストにはスレッド化の問題はありません。保持される唯一の参照は、ReadOnlyCollection<T>ラッパーによるものです。

C - 通常の (書き込み可能な) コピー

return new List<T>(list);

新しいリストを返します。呼び出し元は、元のリストに影響を与えることなく、リストに対して必要な操作を行うことができます。元のリストへの変更は、このリストには影響しません。


別のコンシューマがリストのコピーを取得して、そのコピーを変更しても問題になるでしょうか? 消費者はリストの変更を確認する必要がありますか? スレッドセーフな列挙子だけが必要ですか?

public IEnumerator<T> ThreadSafeEnumerator()
{
    List<T> copy;
    lock(lockable)
        copy = new List<T>(list);

    foreach (var value in copy)
        yield return value;
}
于 2010-02-25T04:08:10.430 に答える
1

私の経験では、スレッドセーフに関しては頭脳を使用する必要があり、これらのようなソリューションに依存する必要はありません。要するに、それはリストの受信者がリストで何をしようとしているかに依存します。

于 2010-02-24T23:46:32.670 に答える
1

Translate() メソッドは正しいようです。ロックを使用すると、Translate/AddRange にいる間、他のユーザーがリストを追加または変更することを防止できます。

ただし、 IsReadyOnly プロパティに問題がある可能性があると思います。内部でプロパティを読み書きするときにロックを使用します。ただし、ロックされていない public getter もあります。IsReadOnly を見ると、スレッド 1 が MarkAsReadOnly を呼び出す一方で、2 番目のスレッドが false になる場合があります。代わりに通常のプロパティを使用し、ゲッターでロックするか、揮発性の bool フィールドを使用します。

于 2010-02-24T23:53:09.863 に答える
1

SynchronizedCollection を使用できます。

http://msdn.microsoft.com/en-us/library/ms668265.aspx

于 2012-08-30T17:29:05.557 に答える