私はアプリケーションに、 をリアルタイムで更新する必要があるドメインオブジェクトのコレクションを持っています。いくつかのスレッドは、このコレクション のアイテムを変更するアクションを実行することができ、安全に行う必要があります。現在のアプローチはむしろ単純に であり、変更を行う前に本質的にグローバルロックをとっています。次のような 多かれ少なかれ何か:アイテムレベルとコレクションレベルの両方のロックを効率的にサポートするにはどうしたらいいですか?
private readonly object lockObject = new object();
private Dictionary<int, Widget> items;
private void UpdateAllWidgets()
{
lock (this.lockObject)
{
// Update all the widgets. No widgets should be permitted to be
// updated while this is running.
}
}
private void UpdateWidget(int widgetId)
{
lock (this.lockObject)
{
// Update the widget with id = widgetId. I want to me able to
// update other widgets at the same time, however.
}
}
ロックが粗すぎるので、私は今、パフォーマンスの問題に実行しています。 単一のアイテムが (同時に他のアイテムを更新できるようにする)の間にアイテムレベルのロックを取ることができるようにしたいが、 は必要なときにコレクションレベルのロックを取ることができる。だから、動作が のように次のようになります:
Thread 1: UpdateWidget(1);
Thread 2: UpdateWidget(2); // This can run before UpdateWidget(1)
// completes.
Thread 1: UpdateWidget(1);
Thread 2: UpdateAllWidgets(); // This has to wait for UpdateWidget(1)
Thread 3: UpdateWidget(2); // This has to wait for UpdateAllWidgets()
Thread 4: UpdateWidget(3); // This has to wait for UpdateAllWidgets(), but
// not UpdateWidget(2)
これをサポートするロック構造上の任意のアイデア?上記の例は が必要ですが簡略版ですが、既に除外しています ConcurrentDictionaryが不十分です。たとえば、 UpdateWidgetで実行されるアクションは、単純なインプレース更新だけではありません。そのアイテムに影響を与えるデータベースの更新が含まれる可能性があります。
私はこの種のシナリオをとったときに両方のアプローチを累積します。 ConcurrentDictionaryですが、変更する前にロックすることができるコンテナに各値をラップします。コレクションレベルのロックを処理するには、グローバルReaderWriterLockSlimを追加する必要があります –
アイテムはマルチスレッドの方法でコレクションに追加されますか(またはコレクションから削除されますか?またはコレクションに静的なサイズがあり、要素が更新されただけですか? –
@ MatiasCicero-はい。アイテムは他のスレッドに追加したり削除したりすることができます。追加はアイテムレベルの更新をブロックするべきではありません。削除するとそのアイテムのみがブロックされます。 –