2

こんにちは、メソッドで writerreaderlock を使用する必要があります。正しい使い方が知りたいです。

ObjectA の辞書を取得しました

public class ObjectA
{
    public ReaderWriterLock RWL {get;set;}
    public ObjectB obj {get;set;}
    public ObjectA()
    {
        RWL = new ReaderWriterLock();
    }
}

public class ObjectB
{
    int TTL {get;set;}
    string Value {get;set;}
}

私のメソッドでは、ObjectA の辞書を使用します。キーは Guid であるため、dict[guid] を呼び出すと、常に ObjectA のインスタンスが返されると仮定します (例として)。

public foo()
{
    ObjecA objA = dict[guid];
    objA.RWL.AcquireReaderLock(500);
    if(objA.obj.TTL<=0)
    {
        objA.obj.RWL.AcquireWriterLock(1000);
        objA.obj.Value = DateTime.Now().ToString();
        objA.obj.RWL.ReleaseWriterLock();
    }else{
         int ttl = objA.obj.TTL;
         Interlocked.Decrement(ref ttl);
    }    
    objA.RWL.ReleaseReaderLock();
}

リーダーとライターの使用方法がよくわかりません。条件付き検証を使用して、リーダーとライターのロックをどのように使用する必要がありましたか?

4

1 に答える 1

6

このコードには、次のような多くの問題があります。

  • クラス インスタンスの TTL を実際にデクリメントしているわけではありません。Nikolai が指摘しているように、ローカル変数をデクリメントしているのです。Interlocked.Decrement(ref objA.obj.TTL)これを適切に行う方法です。
  • 初期 TTL 値を設定していないため、常にゼロになります (他のコードが設定している場合を除きます。これは、通常、すべてのスレッド セーフ関連のコードを同じにする必要があるスレッドに依存するクラスにはおそらく賢明ではありません)。誰が何をしているかを見失うのを避けるためのクラス)
  • 古いReaderWriterLockクラスよりも優先されるようになったReaderWriterLockSlimを使用する必要があります。理由については、後者のハイパーリンクを参照してください。
  • 書き込みロックを取得するときに、既に読み取りロックを取得している場合は、ロックをアップグレードする必要があります。通常、ロック クラスにはそのための別のメソッドがあります。同様に、アップグレード後にロックを解放するには、1 つの方法でロックを解放する必要があります。1 つの方法で書き込みロックを解放し、別の方法で以前の読み取りロックを解放する必要はありません。
  • ロックを取得できないという失敗のケースに対処する必要があります。
  • コードをusingまたはtry/finallyブロックにラップして、例外が発生した場合でもリソースが確実に解放されるようにする必要があります。

lock{}また、ステートメントのような単純なものを使用する代わりに、本当にリーダー/ライター ロックを使用する必要があるかどうかを検討する価値があるかもしれません。リーダー/ライター ロックを正しく取得し、デッドロックを回避することは、これらの API と概念をよく知っている開発者であっても困難であり、その場合でも通常、最もパフォーマンスが重要な場所 (1 秒あたり 1000 以上) にのみ使用を予約します。つまり、 を使用したより単純なアプローチから始めて、パフォーマンスが許容できない場合lock{}にのみ を使用するようにフォールバックする方がよい場合があります。ReaderWriterLockSlim

出発点として、質問にさらに情報を追加することをお勧めします。

  • 最初に、機能とパフォーマンスに関する高レベルの要件など、実行しようとしていることの高レベルの説明を含めます。これは、適切なソリューションを推奨し、リーダー/ライター ロックが適切なアプローチであるかどうかを判断するのに役立ちます。
  • 上記の論理的な問題にどのように対処するか (たとえば、タイムアウトが発生したときにどうするか、TTL をどのように設定するかなど) を含め、コードをどのように動作させたいかを、疑似コードまたは単純な英語で正確に書き出すようにしてください。 )
  • コードサンプルを修正して、上記の問題の一部またはすべての修正を含めます

この追加情報を質問に含めると、残りのコードの問題を解決するのに役立つより良い回答が得られることを保証します. :-)

于 2009-11-04T18:00:42.140 に答える