2012-10-17 5 views

Antwort

7

Nein, die lock-Anweisung entspricht System.Threading.Monitor.Enter() (MSDN) und es gibt keine Überlastung, die einen Prioritätsparameter akzeptiert.

Die nächste Sache, die ich denken kann, ist ein ReaderWriterLock (Slim), aber ich würde ernsthaft überdenken, das Design, das zu dieser Anfrage führt. Es gibt wahrscheinlich bessere Möglichkeiten, um das zu erreichen, was Sie brauchen.

2

Durch eine native Lock-Anweisung, nein. Durch Ihren eigenen benutzerdefinierten Schließmechanismus, sicher, wenn Sie bereit sind, die Zeit und Mühe zu investieren, um es zu entwickeln.

Hier ist mein Entwurf eine Lösung. Es kann oder möglicherweise nicht arbeiten, und ist möglicherweise nicht super effizient, aber es ist mindestens ein Ausgangspunkt:

public class Lock 
{ 
    bool locked = false; 

    private object key = new object(); 
    SortedDictionary<int, Queue<ManualResetEvent>> notifiers = 
     new SortedDictionary<int, Queue<ManualResetEvent>>(); 

    ManualResetEvent specialNotifier = null; 

    public void Lock() 
    { 
     lock (key) 
     { 
      if (locked) 
      { 
       ManualResetEvent notifier = new ManualResetEvent(false); 

       int priority = getPriorityForThread(); 

       Queue<ManualResetEvent> queue = notifiers[priority]; 
       if (queue == null) 
       { 
        queue = new Queue<ManualResetEvent>(); 
        notifiers[priority] = queue; 
       } 

       queue.Enqueue(notifier); 

       notifier.WaitOne(); 
      } 
      else 
      { 
       locked = true; 
      } 
     } 
    } 

    private static int getPriorityForThread() 
    { 
     return 0; 
    } 

    public void Release() 
    { 
     lock (key) 
     { 
      foreach (var queue in notifiers.Values) 
      { 
       if (queue.Any()) 
       { 
        var notifier = queue.Dequeue(); 
        notifier.Set(); 
        return; 
       } 
      } 
      locked = false; 
     } 
    } 
} 
+0

Einfach nur neugierig, gibt es keinen Grund dies nicht IDisposable verwenden könnte? – wwahammy

+0

@wahahammy Es gibt keinen Grund, nein. – Servy

1

Hier ist eine andere Lösung. Ich habe viele Zeilen, aber es ist ziemlich einfach. Die Funktion DoSomethingSingle wird nur ein Thread gleichzeitig aufgerufen, und diejenigen mit dem highPriority Flag werden bevorzugt.

static int numWaiting = 0; 
    static object single = new object(); 

    ResultType DoSomething(string[] argList, bool highPriority = false) 
    { 
     try 
     { 
      if (highPriority) 
      { 
       Interlocked.Increment(ref numWaiting); 
      } 

      for (;;) 
      { 
       lock (single) 
       { 
        if (highPriority || numWaiting == 0) 
        { 
         return DoSomethingSingle(argList); 
        } 
       } 
       // Sleep gives other threads a chance to enter the lock 
       Thread.Sleep(0); 
      } 
     } 
     finally 
     { 
      if (highPriority) 
      { 
       Interlocked.Decrement(ref numWaiting); 
      } 
     } 
    } 

Dies ermöglicht zwei Prioritätsstufen. Garantiert, dass ein Thread mit niedriger Priorität nur dann auf die Ressource zugreifen kann, wenn keine Threads mit hoher Priorität darauf warten.

edit: Änderung Interlock incr/dec

Verwandte Themen