16

私はしばらくの間ReaderWriterLockSlimを使用してきましたが、これまでのニーズを満たしています。ReaderWriterLockSlimアプリケーションを微調整し続けると、それは私のユースケースには少し最適では ないことがわかります。

ドキュメント(および私の経験)によれば、それはリーダーよりもライターを優先します(つまり、リーダーとライターがキューに入れられている場合、ライターが優先されます)。ただし、読者に有利な同等のものが必要です。そのようなコンポーネントの副作用(特に、ライターの枯渇の問題)を理解しています。

誰かが指摘できる本番環境に対応したものはありますか?ありがとう。

4

1 に答える 1

7

MSDNによると、ReaderWriterLockSlimはライターを支持しています。これは、キューにリーダーとライターがいる場合、ライターが優先されることを意味します。

これはリーダーの飢餓を引き起こす可能性があり、これを再現するためのテストコードはここにあります。書き込みがスレッドコンテキストスイッチを含む長い操作である場合にのみ、枯渇が発生する可能性があると思います。少なくとも私のマシンでは常に再現されているので、間違っているかどうか教えてください。

一方、.net 2.0のReaderWriterLockは、パフォーマンスの低下を犠牲にして、リーダーもライターの枯渇も引き起こしません。これは、飢餓が発生していないことを示すために、前のサンプルから変更されたコードです。

それで、あなたの質問に戻ります-それはあなたがRWロックからどの機能を必要とするかによります。再帰的ロック、例外処理、タイムアウト-上記のすべてをサポートし、リーダーを優先する本番品質のRWロックに最も近いものはおそらくReaderWriterLockでしょう。

また、最初のリーダーとライターの問題を説明するwiki記事のコードを採用することもできますが、もちろん、上記の必要な機能をすべて手動で実装する必要があり、実装にはライター不足の問題があります。

ロックコアはおそらく次のようになります。

class AutoDispose : IDisposable 
{ 
  Action _action; 
  public AutoDispose(Action action) 
  { 
    _action = action; 
  }
  public void Dispose()
  {
    _action();
  }
}

class Lock
{
  SemaphoreSlim wrt = new SemaphoreSlim(1);
  int readcount=0;

  public IDisposable WriteLock()
  {
    wrt.Wait();
    return new AutoDispose(() => wrt.Release());
  }

  public IDisposable ReadLock()
  {
    if (Interlocked.Increment(ref readcount) == 1)
        wrt.Wait();

    return new AutoDispose(() => 
    {
      if (Interlocked.Decrement(ref readcount) == 0)
         wrt.Release();
    });
  }
}

3つのリーダースレッドと3つのライタースレッドを使用し、単純なメモリ内操作を使用して、3つの実装のパフォーマンスを比較します(長いブロッキング操作を使用すると、RWLockSlimのリーダーが不足し、カスタムロックのライターが不足します)。

パフォーマンスの比較

ワークロードループがコンパイラーによって展開されないことを確認しましたが、私が気付いていない他の落とし穴がある可能性があるので、これらの測定を一粒の塩で行います。テストのソースコードはこちらです。

于 2013-04-11T09:08:37.617 に答える