2011-01-15 25 views
4

.NET Frameworkは、そのリソースにアクセスしようとするライターの中には、他のリソースよりも優先されるような方法で、共有リソースへのアクセスを実装する機能を備えていますか?
リソースにのみ、1同時書き込み要求を付与することができます 1.
2.あり、このリソースへのアクセスを待っている多くの作家がありますが、いくつかの作家が他よりも優先されます(飢餓:共有リソースへのライターの優先アクセス?

私の問題は、次の制約があります優先度の低いライターは大丈夫です)。
3.スレッド親和性はNON-requirementです。 1つのスレッドでロックを設定できますが、別のスレッドでロックをリセットできます。
4.すべてのWriterスレッドは同じプロセスからのものです。

要するに、私は待ち行列を公開し、それに対する変更アクセスを可能にするプリミティブが必要です。そのようなものがない場合は、セマフォーのような既に利用可能なクラスを使用して自分自身でビルドを進める方法についてのヒントを教えてください。

+0

に動作しますか?ストリームのようなもの? –

+0

Writerをロックしようとすると、優先順位付けされたキューに自分自身を投げることができない場合はどうですか?ロック付きの書き込みがロックを解放しようとしているとき、キューをチェックして次のライターをつかむことができます。 – kenny

+0

@Will - リソースは、それによって公開されるメソッドまたはプロパティへの同時アクセスを許可しないCOM dllです。同時アクセスが発生した場合の「オブジェクトはまだ準備されていません」COMExceptionをスローします。 @kenny - 私はあなたのアイデアを使用することができたら、私は明日返信すると思います(ここは深夜です)。 – Satyajit

答えて

0

保留中の要求のリストを保持するには、優先度キューを使用します。参照:Priority queue in .Net kennyが提案したように、stanadrdモニタ機能を使用して、実行するタイミングと時刻をロックして通知します。

+0

それはうまくいく、私はそれをやろうとします。また、.NET Framework 4では、System.Threading.CountdownEventという新しいクラスがあり、それを使用して独自のメカニズムを作成できたようです。私はいくつかのperfランを実行して、どのインプリメンテーション(優先度キュー+ミューテックス/モニタ、または自分のクラス)がよりリソース消費量が少ないか確認します。 – Satyajit

1

ここに、私が思いつくクイックなコードがあります。私はこれを改良しますが、POCとして、これはどのようなリソース...

public class PrioritisedLock 
{ 
    private List<CountdownEvent> waitQueue; //wait queue for the shared resource 
    private Semaphore waitQueueSemaphore; //ensure safe access to wait queue itself 

    public PrioritisedLock() 
    { 
     waitQueue = new List<CountdownEvent>(); 
     waitQueueSemaphore = new Semaphore(1, 1); 
    } 

    public bool WaitOne(int position = 0) 
    { 
     //CountdownEvent needs to have a initial count of 1 
     //otherwise it is created in signaled state 
     position++; 
     bool containsGrantedRequest = false; //flag to check if wait queue still contains object which owns the lock 

     CountdownEvent thisRequest = position<1 ? new CountdownEvent(1) : new CountdownEvent(position); 
     int leastPositionMagnitude=Int32.MaxValue; 
     waitQueueSemaphore.WaitOne(); 

     //insert the request at the appropriate position 
     foreach (CountdownEvent cdEvent in waitQueue) 
     { 
      if (cdEvent.CurrentCount > position) 
       cdEvent.AddCount(); 
      else if (cdEvent.CurrentCount == position) 
       thisRequest.AddCount(); 

      if (cdEvent.CurrentCount == 0) 
       containsGrantedRequest = true; 
     } 

     waitQueue.Add(thisRequest); 

     foreach (CountdownEvent cdEvent in waitQueue) 
      if (cdEvent.CurrentCount < leastPositionMagnitude) 
       leastPositionMagnitude = cdEvent.CurrentCount; 

     //If nobody holds the lock, grant the lock to the current request 
     if (containsGrantedRequest==false && thisRequest.CurrentCount == leastPositionMagnitude) 
      thisRequest.Signal(leastPositionMagnitude); 

     waitQueueSemaphore.Release(); 

     //now do the actual wait for this request; if it is already signaled, it ends immediately 
     thisRequest.Wait(); 

     return true; 
    } 

    public int Release() 
    { 
     int waitingCount = 0, i = 0, positionLeastMagnitude=Int32.MaxValue; 
     int grantedIndex = -1; 

     waitQueueSemaphore.WaitOne(); 

     foreach(CountdownEvent cdEvent in waitQueue) 
     { 
      if (cdEvent.CurrentCount <= 0) 
      { 
       grantedIndex = i; 
       break; 
      } 
      i++; 
     } 

     //remove the request which is already fulfilled 
     if (grantedIndex != -1) 
      waitQueue.RemoveAt(grantedIndex); 

     //find the wait count of the first element in the queue 
     foreach (CountdownEvent cdEvent in waitQueue) 
      if (cdEvent.CurrentCount < positionLeastMagnitude) 
       positionLeastMagnitude = cdEvent.CurrentCount; 

     //decrement the wait counter for each waiting object, such that the first object in the queue is now signaled 
     foreach (CountdownEvent cdEvent in waitQueue) 
     { 
      waitingCount++; 
      cdEvent.Signal(positionLeastMagnitude); 
     } 

     waitQueueSemaphore.Release(); 
     return waitingCount; 
    } 
} 

}

+0

これを少し最適化する方法についてのコメントもありがとうございます。 – Satyajit

関連する問題