2011-08-03 9 views
3

私のアプリケーションでは、いくつかのオブジェクトへのアクセスをシリアル化する必要があるロックのコレクションを管理しています(各オブジェクトにロックが割り当てられています)。このロックのコレクション(ロックマネージャ)はスレッドセーフな方法で維持する必要があります(新しいロックが追加されます/古いロックはシリアル化を必要とする新しいオブジェクトが追加/削除されると削除されます)。二行を入れ替えるロックを解除して別のアトミックに取得する方法

LockManager.Lock(); 
var myLock = LockManager.FindLock(myObject); 
LockManager.Unlock();       // atomic 
myLock.Lock();         // atomic 

は良い解決策ではありません: アルゴリズムは、このような何かを動作します。 myLockのロックがブロックされた場合、これはまた、LockManagerのロック解除をブロックして、他のロックの要求をブロックします。

私が必要とするのは、2つのマークされた行がアトミックに実行されることです。これを達成する方法はありますか?

+2

マネージャをロック解除する前にロックを解除するのはなぜですか? – CodesInChaos

+0

別のロックを使用するだけではいかがですか?理性的なロック。 – CodingBarfield

+0

@CodeInChaos: 他のロックブロックの場合、最初のロックの解除もその期間中ブロックされます。 –

答えて

3

だから、あなたがしたい:(myLock経由)個々のロックという

  • 保証はLockManager
  • が、これは新しい許可
  • アトミック上記の2つの操作を行うことなく、ロックの解除を
  • を入力しましたロックをすぐに入力できない場合にブロックするアトミック操作

永遠のモーションマシンを作るために物理学の法則を迂回することはできないのと同様に、あなたは、たとえたとえその構成要素のうちの1つが可能であっても妨げないような方法で原子的に一連の演算を実行することによって、事実、ブロックされることが予想される。言い換えれば、個々の部品も完成するまで、操作を完了させる方法はありません。

しかし、私たちができることは、 "none"の結果があればブロックされないオールアロケーションでもアトミックでもこのアトミックな操作を試みることです。多くの同時データ構造上に存在するTryXXXメソッドを使用すると、多くのことがわかります。 myLockタイプでTryLockを定義するだけです。次に、LockManagerは次のようになります。

public class LockManager 
{ 
    public bool TryEnterIndividualLock(object value) 
    { 
    Lock(); 
    try 
    { 
     var myLock = FindLock(value); 
     if (myLock != null) 
     { 
     return myLock.TryLock(); 
     } 
     return false; 
    } 
    finally 
    { 
     Unlock(); 
    } 
    } 
} 

そして、呼び出し元のコードは次のようになります。

while (!LockManager.TryEnterIndividualLock(myObject)) 
{ 
    // Do something else until the lock can be entered. 
} 

これはあなたが探していた原子性を与えるが、操作のコストで成功しないでしょう。すぐに成功するこの操作に頼っているなら、あなたは全体のデザインを再考する必要があります。

関連する問題