3

複数のスレッド間で共有される辞書があります。すべてのスレッドは、指定されたキーに従ってディクショナリから特定の値を読み取りますが、キーがディクショナリに存在しない場合、スレッドはそれをディクショナリに追加する必要があります。
同期の問題を解決するために、基本的にリーダーとライターのロック同期を提供する ReaderWriterLockSlim クラスを使用します (つまり、リーダーは並行して実行できますが、一度に 1 つのライターしか実行できません...) が、リーダーのアップグレード オプションを追加します。アップグレード オプションを使用すると、特定のキーが既にディクショナリにあるかどうかをテストできます。そうでない場合は、ロックをアップグレードして書き込み、キーごとに 1 つの追加のみを約束します。

私の問題は、一度に 2 つのアップグレード可能なロックを作成できないことです。つまり、この解決策は役に立ちません... :(

Microsoft がアップグレード可能なロックをこのように実装することを選択した理由 (一度に複数のアップグレード可能なロックを使用することはできません...) を説明してください。また、アップグレード可能なロックを自分で実装する方法を教えてください共有辞書を同期する別のアイデアはありますか?

4

4 に答える 4

8

.NET 4.0 を使用している場合、ConcurrentDictionaryを使用しない理由

于 2011-09-26T20:05:05.327 に答える
4

なぜReaderWriterLockSlimそのように実装されたのかわかりません。正当な理由があると思います。

ConcurrentDictionaryを使用しないのはなぜですか? そうすれば、明示的なロックについて心配する必要はありません。

とは言っても、複数のアップグレード可能なリーダー ロックがどこで役立つかはわかりません。次のシナリオを検討してください。

Thread1 enters the lock in upgradeable mode
Thread2 enters the lock in upgradeable mode
Thread1 searches for "xyzzy" and doesn't find it
Thread2 searches for "xyzzy" and doesn't find it
Thread2 upgrades to a write lock
Thread1 waits to upgrade to a write lock
Thread2 updates and releases the lock
Thread1 acquires the write lock and overwrites what Thread2 had written

Thread1 が Thread2 の動作を上書きしないようにするには、次のロジックを記述する必要があります。

Enter upgradable read lock
if (!dict.TryGetValue(...))
{
    Enter write lock
    if (!dict.TryGetValue(...))  // extra check required!
    {
    }
}

アップグレード可能なロックがない場合、これはまさにあなたがしなければならないことです。

于 2011-09-26T20:05:39.403 に答える
1

UpgradeableReadLock が存在するため、書き込みロックを取得する前に読み取りロックを解放する必要はありません。これを行うことができます:

   locker.EnterUpgradeableReadLock();
   ...
   locker.EnterWriteLock(); 
   ...

それ以外の

   locker.EnterReadLock();
   ...
   locker.ExitReadLock();
   locker.EnterWriteLock();
   ...

これは ReaderWriter ロックであるため、アップグレード可能な読み取りロックが適用されるライターは常に 1 つしかない可能性があります。これは、これら 2 つが同等ではないことを意味します。1 つ目は、他の呼び出し元が侵入できるようにしますが、読み取り部分での同時実行を許可します。

ほとんどの読み取りに ReadLocks を使用し、データの更新/挿入に UpgradeableRead を使用できる場合は、これが目的です。すべてのデータアクセスが潜在的なライターである場合、これはおそらくうまく機能せず、書き込みの周りに単純な lock(object) を使用して、追加/更新時に排他アクセスを強制できます。

于 2011-09-26T20:14:27.123 に答える
-2

おそらく、この問題の最適なソリューションを使用しているようには思えません。

例:

  protected static object _lockObj = new object();

  if(_dictionary.ContainsKey(key))
  {
      return _dictionary[key];
  }
  else
  {
      lock(_lockObj)
      {
           if(_dictionary.ContainsKey(key))
              return _dictionary[key];

           _dictionary.Add(key, "someValue");
           return "someValue";
      }
  }

.NET 4を使用している場合は、他の人が言及しているConcurrentDictionaryクラスを使用してみてください。

于 2011-09-26T20:06:40.463 に答える