3

私はDictionary<object1, List<object2>(もう少し複雑な、私の構造のために作成した抽象化)を持っています。

ディクショナリ内のリストは非並列コンテキストで初期化されますが、リストに新しい要素を追加するには、スレッドセーフなメソッドが必要です。アイテムの削除は発生しません(ディクショナリオブジェクトはトランザクションの最後に破棄されます)。また、キーと値のペアは初期化時にのみ追加されるため、作業中にキーが追加またはディクショナリから削除されることはなく、値のみが更新されます。

同時コレクションを使用できません。古い.NETFrameworkでスタックしています。

最初は、辞書全体を。でロックしましたReadWriteSlimlock。まあ、これはパフォーマンス的には非常に悪いものでした。多くの加算操作が行われていて、それらは別の操作を待つだけです。少なくとも私は各キーに対して並行して作業を行っているため、各リストのみをロックする方がはるかに優れたソリューションです。また、追加操作は単純list.Add(object2)ではありません。追加時にスレッドセーフ領域で他の複雑な操作を実行する必要があります。

しかし、私はそれを実装するための最良の方法が何であるかわかりません:

  1. lock(dictionary.Value)
  2. ReadWriteSlimlock(キーごとに1つ)の辞書を使用しますか?
  3. 他のより良い解決策はありますか?
4

3 に答える 3

2

List<object>別の解決策は、並行クラスを実装することです。何かのようなもの:

public class ConcurentList {
    private object sync = new object(); 
    private List<object> realList = new List<object>(); 


    public void Add(object o) {
        lock(sync){
           realList.Add(o);
        }
    }   

    /** ADD OTHERE METHODS IMPEMENTATION IF NEED **/

}

そして辞書には次のものがあります:

Dictionary<object1, ConcurentList>

カプセル化して拡張しない理由List<object>は、Addメソッドが仮想ではないため、それを「オーバーライド」できる唯一の方法は、キーワードを使用することです。これは、まったく同じ typeで使用された場合にのみnew呼び出されることが保証されています。つまり、リストをキャストした場合呼び出されないため、ホール アーキテクチャは失敗します。

カプセル化することで、すべてを制御するメソッドを 1 つだけ呼び出し元に渡します。

このソリューションがニーズに合っているかどうかはわかりませんが、物事を管理する方法についてのヒントが得られることを願っています.

于 2013-01-17T11:49:45.737 に答える
1

と の独自の並行スレッドセーフバリアントを作成してみませんDictionary<>List<>? これは私が .NET 2 に対して行ったことです。

個人的には を選択しましたReaderWriterLockSlim。アクセス パターンに基づいてロックを制御できるためです。ほとんどの場合、リストは書き込み先よりも多くのものか​​ら読み取られていました。

ただし、多くの追加を行っているため、(lockReaderWriterLockSlim) の両方を試して、どちらのパフォーマンスが優れているかを確認することをお勧めします。

于 2013-01-17T11:42:47.210 に答える
1

リストからの読み取りが書き込みと同時にReaderWriterLockSlim行われる場合、複数のリーダーが同じリストで同時に処理できるため、辞書エントリごとにオブジェクトを構築することが最適なソリューションになります。を使用するよりもわずかに難しいだけlock(key)であり、少数のリストが他のリストよりも頻繁に読み取られる場合に、パフォーマンスが向上する可能性があります。

ルートをたどる場合ReaderWriterLockSlimは、リーダー/ライター ロック専用の個別の辞書を作成するのではなく、リストとロックを 1 つのクラスにラップすることをお勧めします。

class LockableList {
    public ReaderWriterLockSlim RwLock {get;private set;}
    public List<object2> Data {get;private set;}
    public LockableList() {
        RwLock = new ReaderWriterLockSlim();
        Data = new List<object2>();
    }
}
...
Dictionary<object1,LockableList> myDictionary;

リストとルックを組み合わせると、ディクショナリ エントリを 1 回検索し、必要に応じて読み取りまたは書き込みのためにロックし、関連付けられたリストで作業を行うことができます。

于 2013-01-17T11:49:01.893 に答える