8

コードの重要な部分を保護するためにlock ステートメントを使用してきましたが、いくつかの条件が満たされれば、その重要なコードの同時実行を許可できることに気付きました。
ロックを調整する方法はありますか?

4

8 に答える 8

11

その質問は「レースコンディション!」と叫ぶと思います。チェックの直後で、スレッドがコードのクリティカル セクションに入る前に、条件が true から false に変わったらどうなるでしょうか。それとも、スレッドが実行中ですか?

于 2008-10-28T12:59:34.183 に答える
8
bool locked = false;
if (condition) {
    Monitor.Enter(lockObject);
    locked = true;
}
try {
    // possibly critical section
}
finally {
    if (locked) Monitor.Exit(lockObject);
}

EDIT:はい、スレッドが入っている間、条件が一定であることを保証できない限り、競合状態があります。

于 2008-10-28T13:02:01.383 に答える
8

私はスレッドの専門家ではありませんが、このようなもの (二重チェックのロック) を探しているようです。アイデアは、ロックを取得する前後の状態をチェックすることです。

private static object lockHolder = new object();

if (ActionIsValid()) {
  lock(lockHolder) {
    if (ActionIsValid()) {
       DoSomething();    
    }
  }
}
于 2008-10-28T15:29:03.443 に答える
7
Action doThatThing = someMethod;

if (condition)
{
  lock(thatThing)
  {
     doThatThing();
  }
}
else
{
  doThatThing();
}
于 2008-10-28T12:57:11.723 に答える
6

実際には、競合状態を回避するために、ReaderWriterLockSlim同時アクセスを読み取りロックとして扱い、排他的アクセスを書き込みロックとして扱います。そうすれば、条件が変わっても、不適切なコードがその領域で盲目的に実行されることはありません (安全であるという誤った仮定の下で)。少し冗長ですが(スペース用にフォーマットされています):

        if (someCondition) {
            lockObj.EnterReadLock();
            try { Foo(); }
            finally { lockObj.ExitReadLock(); }
        } else {
            lockObj.EnterWriteLock();
            try { Foo(); }
            finally { lockObj.ExitWriteLock(); }
        }
于 2008-10-28T13:01:08.610 に答える
1

次のようなコードがあると思います。

private Monkey GetScaryMonkey(int numberOfHeads){
    Monkey ape = null;        
    lock(this) {
        ape = new Monkey();
        ape.AddHeads(numberOfHeads);            
    }
    return ape;
}

これを条件付きにするために、これを行うことはできませんでした:

private Monkey GetScaryMonkey(int numberOfHeads){
    if ( numberOfHeads > 1 ) {
         lock(this) {
            return CreateNewMonkey( numberOfHeads );          
        }
    }
    return CreateNewMonkey( numberOfHeads );
}

うまくいくはずですよね?

于 2008-10-28T12:58:56.913 に答える
1

上記のように、ダブルチェック ロック パターンを使用します。それがトリックIMOです:)

not.that.dave.foley.myopenid.com の例に記載されているように、ロック オブジェクトがstaticであることを確認してください。

于 2008-11-10T05:52:25.673 に答える