ReaderWriterLockSlim Class

Definition

Stellt eine Sperre dar, mit der der Zugriff auf eine Ressource verwaltet wird. Mehrere Threads können damit Lesezugriff oder exklusiven Schreibzugriff erhalten.Represents a lock that is used to manage access to a resource, allowing multiple threads for reading or exclusive access for writing.

public ref class ReaderWriterLockSlim : IDisposable
public class ReaderWriterLockSlim : IDisposable
type ReaderWriterLockSlim = class
    interface IDisposable
Public Class ReaderWriterLockSlim
Implements IDisposable
Inheritance
ReaderWriterLockSlim
Implements

Examples

Das folgende Beispiel zeigt einen einfachen synchronisierten Cache, der Zeichen folgen mit ganzzahligen Schlüsseln enthält.The following example shows a simple synchronized cache that holds strings with integer keys. Eine Instanz von ReaderWriterLockSlim wird zum Synchronisieren des Zugriffs auf die Dictionary<TKey,TValue> verwendet, die als innerer Cache fungiert.An instance of ReaderWriterLockSlim is used to synchronize access to the Dictionary<TKey,TValue> that serves as the inner cache.

Das Beispiel enthält einfache Methoden, die dem Cache hinzugefügt, aus dem Cache gelöscht und aus dem Cache gelesen werden.The example includes simple methods to add to the cache, delete from the cache, and read from the cache. Um Timeouts zu veranschaulichen, enthält das Beispiel eine-Methode, die nur dann dem Cache hinzugefügt wird, wenn dies innerhalb eines angegebenen Timeouts möglich ist.To demonstrate time-outs, the example includes a method that adds to the cache only if it can do so within a specified time-out.

Um den erweiterbaren Modus zu veranschaulichen, enthält das Beispiel eine Methode, die den einem Schlüssel zugeordneten Wert abruft und ihn mit einem neuen Wert vergleicht.To demonstrate upgradeable mode, the example includes a method that retrieves the value associated with a key and compares it with a new value. Wenn der Wert unverändert ist, gibt die Methode einen Status zurück, der angibt, dass keine Änderungen vorgenommen wurden.If the value is unchanged, the method returns a status indicating no change. Wenn kein Wert für den Schlüssel gefunden wird, wird das Schlüssel-Wert-Paar eingefügt.If no value is found for the key, the key/value pair is inserted. Wenn der Wert geändert wurde, wird er aktualisiert.If the value has changed, it is updated. Der aktualisierbare Modus ermöglicht es dem Thread, bei Bedarf von Lesezugriff auf Schreibzugriff zu aktualisieren, ohne dass Deadlocks gefährdet sind.Upgradeable mode allows the thread to upgrade from read access to write access as needed, without the risk of deadlocks.

Das Beispiel enthält eine geschaltete Enumeration, die die Rückgabewerte für die Methode angibt, die den aktualisierbaren Modus veranschaulicht.The example includes a nested enumeration that specifies the return values for the method that demonstrates upgradeable mode.

Im Beispiel wird der Parameter lose Konstruktor verwendet, um die Sperre zu erstellen, sodass Rekursion nicht zulässig ist.The example uses the parameterless constructor to create the lock, so recursion is not allowed. Das Programmieren der ReaderWriterLockSlim ist einfacher und weniger fehleranfällig, wenn die Sperre keine Rekursion zulässt.Programming the ReaderWriterLockSlim is simpler and less prone to error when the lock does not allow recursion.

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
Imports System.Collections.Generic
Imports System.Threading
Imports System.Threading.Tasks

public class SynchronizedCache 
{
    private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();
    private Dictionary<int, string> innerCache = new Dictionary<int, string>();

    public int Count
    { get { return innerCache.Count; } }

    public string Read(int key)
    {
        cacheLock.EnterReadLock();
        try
        {
            return innerCache[key];
        }
        finally
        {
            cacheLock.ExitReadLock();
        }
    }

    public void Add(int key, string value)
    {
        cacheLock.EnterWriteLock();
        try
        {
            innerCache.Add(key, value);
        }
        finally
        {
            cacheLock.ExitWriteLock();
        }
    }

    public bool AddWithTimeout(int key, string value, int timeout)
    {
        if (cacheLock.TryEnterWriteLock(timeout))
        {
            try
            {
                innerCache.Add(key, value);
            }
            finally
            {
                cacheLock.ExitWriteLock();
            }
            return true;
        }
        else
        {
            return false;
        }
    }

    public AddOrUpdateStatus AddOrUpdate(int key, string value)
    {
        cacheLock.EnterUpgradeableReadLock();
        try
        {
            string result = null;
            if (innerCache.TryGetValue(key, out result))
            {
                if (result == value)
                {
                    return AddOrUpdateStatus.Unchanged;
                }
                else
                {
                    cacheLock.EnterWriteLock();
                    try
                    {
                        innerCache[key] = value;
                    }
                    finally
                    {
                        cacheLock.ExitWriteLock();
                    }
                    return AddOrUpdateStatus.Updated;
                }
            }
            else
            {
                cacheLock.EnterWriteLock();
                try
                {
                    innerCache.Add(key, value);
                }
                finally
                {
                    cacheLock.ExitWriteLock();
                }
                return AddOrUpdateStatus.Added;
            }
        }
        finally
        {
            cacheLock.ExitUpgradeableReadLock();
        }
    }

    public void Delete(int key)
    {
        cacheLock.EnterWriteLock();
        try
        {
            innerCache.Remove(key);
        }
        finally
        {
            cacheLock.ExitWriteLock();
        }
    }

    public enum AddOrUpdateStatus
    {
        Added,
        Updated,
        Unchanged
    };

    ~SynchronizedCache()
    {
       if (cacheLock != null) cacheLock.Dispose();
    }
}
Public Class SynchronizedCache
    Private cacheLock As New ReaderWriterLockSlim()
    Private innerCache As New Dictionary(Of Integer, String)

    Public ReadOnly Property Count As Integer
       Get
          Return innerCache.Count
       End Get
    End Property
    
    Public Function Read(ByVal key As Integer) As String
        cacheLock.EnterReadLock()
        Try
            Return innerCache(key)
        Finally
            cacheLock.ExitReadLock()
        End Try
    End Function

    Public Sub Add(ByVal key As Integer, ByVal value As String)
        cacheLock.EnterWriteLock()
        Try
            innerCache.Add(key, value)
        Finally
            cacheLock.ExitWriteLock()
        End Try
    End Sub

    Public Function AddWithTimeout(ByVal key As Integer, ByVal value As String, _
                                   ByVal timeout As Integer) As Boolean
        If cacheLock.TryEnterWriteLock(timeout) Then
            Try
                innerCache.Add(key, value)
            Finally
                cacheLock.ExitWriteLock()
            End Try
            Return True
        Else
            Return False
        End If
    End Function

    Public Function AddOrUpdate(ByVal key As Integer, _
                                ByVal value As String) As AddOrUpdateStatus
        cacheLock.EnterUpgradeableReadLock()
        Try
            Dim result As String = Nothing
            If innerCache.TryGetValue(key, result) Then
                If result = value Then
                    Return AddOrUpdateStatus.Unchanged
                Else
                    cacheLock.EnterWriteLock()
                    Try
                        innerCache.Item(key) = value
                    Finally
                        cacheLock.ExitWriteLock()
                    End Try
                    Return AddOrUpdateStatus.Updated
                End If
            Else
                cacheLock.EnterWriteLock()
                Try
                    innerCache.Add(key, value)
                Finally
                    cacheLock.ExitWriteLock()
                End Try
                Return AddOrUpdateStatus.Added
            End If
        Finally
            cacheLock.ExitUpgradeableReadLock()
        End Try
    End Function

    Public Sub Delete(ByVal key As Integer)
        cacheLock.EnterWriteLock()
        Try
            innerCache.Remove(key)
        Finally
            cacheLock.ExitWriteLock()
        End Try
    End Sub

    Public Enum AddOrUpdateStatus
        Added
        Updated
        Unchanged
    End Enum

    Protected Overrides Sub Finalize()
       If cacheLock IsNot Nothing Then cacheLock.Dispose()
    End Sub
End Class

Im folgenden Code wird dann das SynchronizedCache-Objekt verwendet, um ein Wörterbuch mit den Namen von Pflanzen zu speichern.The following code then uses the SynchronizedCache object to store a dictionary of vegetable names. Es werden drei Aufgaben erstellt.It creates three tasks. Der erste schreibt die in einem Array gespeicherten Namen von Gemüse in eine SynchronizedCache-Instanz.The first writes the names of vegetables stored in an array to a SynchronizedCache instance. In der zweiten und dritten Aufgabe werden die Namen des Gemüses angezeigt, der erste in aufsteigender Reihenfolge (von niedrigem Index bis zu hohem Index), der zweite in absteigender Reihenfolge.The second and third task display the names of the vegetables, the first in ascending order (from low index to high index), the second in descending order. Die letzte Aufgabe sucht nach der Zeichenfolge "gurber" und ruft, wenn Sie gefunden wird, die EnterUpgradeableReadLock-Methode auf, um die Zeichenfolge "grünes Bean" zu ersetzen.The final task searches for the string "cucumber" and, when it finds it, calls the EnterUpgradeableReadLock method to substitute the string "green bean".

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
Imports System.Collections.Generic
Imports System.Threading
Imports System.Threading.Tasks

public class Example
{
   public static void Main()
   {
      var sc = new SynchronizedCache();
      var tasks = new List<Task>();
      int itemsWritten = 0;

      // Execute a writer.
      tasks.Add(Task.Run( () => { String[] vegetables = { "broccoli", "cauliflower",
                                                          "carrot", "sorrel", "baby turnip",
                                                          "beet", "brussel sprout",
                                                          "cabbage", "plantain",
                                                          "spinach", "grape leaves",
                                                          "lime leaves", "corn",
                                                          "radish", "cucumber",
                                                          "raddichio", "lima beans" };
                                  for (int ctr = 1; ctr <= vegetables.Length; ctr++)
                                     sc.Add(ctr, vegetables[ctr - 1]);

                                  itemsWritten = vegetables.Length;
                                  Console.WriteLine("Task {0} wrote {1} items\n",
                                                    Task.CurrentId, itemsWritten);
                                } ));
      // Execute two readers, one to read from first to last and the second from last to first.
      for (int ctr = 0; ctr <= 1; ctr++) {
         bool desc = Convert.ToBoolean(ctr);
         tasks.Add(Task.Run( () => { int start, last, step;
                                     int items;
                                     do {
                                        String output = String.Empty;
                                        items = sc.Count;
                                        if (! desc) {
                                           start = 1;
                                           step = 1;
                                           last = items;
                                        }
                                        else {
                                           start = items;
                                           step = -1;
                                           last = 1;
                                        }

                                        for (int index = start; desc ? index >= last : index <= last; index += step)
                                           output += String.Format("[{0}] ", sc.Read(index));

                                        Console.WriteLine("Task {0} read {1} items: {2}\n",
                                                          Task.CurrentId, items, output);
                                     } while (items < itemsWritten | itemsWritten == 0);
                             } ));
      }
      // Execute a red/update task.
      tasks.Add(Task.Run( () => { Thread.Sleep(100);
                                  for (int ctr = 1; ctr <= sc.Count; ctr++) {
                                     String value = sc.Read(ctr);
                                     if (value == "cucumber")
                                        if (sc.AddOrUpdate(ctr, "green bean") != SynchronizedCache.AddOrUpdateStatus.Unchanged)
                                           Console.WriteLine("Changed 'cucumber' to 'green bean'");
                                  }
                                } ));

      // Wait for all three tasks to complete.
      Task.WaitAll(tasks.ToArray());

      // Display the final contents of the cache.
      Console.WriteLine();
      Console.WriteLine("Values in synchronized cache: ");
      for (int ctr = 1; ctr <= sc.Count; ctr++)
         Console.WriteLine("   {0}: {1}", ctr, sc.Read(ctr));
   }
}
// The example displays the following output:
//    Task 1 read 0 items:
//
//    Task 3 wrote 17 items
//
//
//    Task 1 read 17 items: [broccoli] [cauliflower] [carrot] [sorrel] [baby turnip] [
//    beet] [brussel sprout] [cabbage] [plantain] [spinach] [grape leaves] [lime leave
//    s] [corn] [radish] [cucumber] [raddichio] [lima beans]
//
//    Task 2 read 0 items:
//
//    Task 2 read 17 items: [lima beans] [raddichio] [cucumber] [radish] [corn] [lime
//    leaves] [grape leaves] [spinach] [plantain] [cabbage] [brussel sprout] [beet] [b
//    aby turnip] [sorrel] [carrot] [cauliflower] [broccoli]
//
//    Changed 'cucumber' to 'green bean'
//
//    Values in synchronized cache:
//       1: broccoli
//       2: cauliflower
//       3: carrot
//       4: sorrel
//       5: baby turnip
//       6: beet
//       7: brussel sprout
//       8: cabbage
//       9: plantain
//       10: spinach
//       11: grape leaves
//       12: lime leaves
//       13: corn
//       14: radish
//       15: green bean
//       16: raddichio
//       17: lima beans
Public Module Example
   Public Sub Main()
      Dim sc As New SynchronizedCache()
      Dim tasks As New List(Of Task)
      Dim itemsWritten As Integer
      
      ' Execute a writer.
      tasks.Add(Task.Run( Sub()
                             Dim vegetables() As String = { "broccoli", "cauliflower",
                                                            "carrot", "sorrel", "baby turnip",
                                                            "beet", "brussel sprout",
                                                            "cabbage", "plantain",
                                                            "spinach", "grape leaves",
                                                            "lime leaves", "corn",
                                                            "radish", "cucumber",
                                                            "raddichio", "lima beans" }
                             For ctr As Integer = 1 to vegetables.Length
                                sc.Add(ctr, vegetables(ctr - 1))
                             Next
                             itemsWritten = vegetables.Length
                             Console.WriteLine("Task {0} wrote {1} items{2}",
                                               Task.CurrentId, itemsWritten, vbCrLf)
                          End Sub))
      ' Execute two readers, one to read from first to last and the second from last to first.
      For ctr As Integer = 0 To 1
         Dim flag As Integer = ctr
         tasks.Add(Task.Run( Sub()
                                Dim start, last, stp As Integer
                                Dim items As Integer
                                Do
                                   Dim output As String = String.Empty
                                   items = sc.Count
                                   If flag = 0 Then
                                      start = 1 : stp = 1 : last = items
                                   Else
                                      start = items : stp = -1 : last = 1
                                   End If
                                   For index As Integer = start To last Step stp
                                      output += String.Format("[{0}] ", sc.Read(index))
                                   Next
                                   Console.WriteLine("Task {0} read {1} items: {2}{3}",
                                                           Task.CurrentId, items, output,
                                                           vbCrLf)
                                Loop While items < itemsWritten Or itemsWritten = 0
                             End Sub))
      Next
      ' Execute a red/update task.
      tasks.Add(Task.Run( Sub()
                             For ctr As Integer = 1 To sc.Count
                                Dim value As String = sc.Read(ctr)
                                If value = "cucumber" Then
                                   If sc.AddOrUpdate(ctr, "green bean") <> SynchronizedCache.AddOrUpdateStatus.Unchanged Then
                                      Console.WriteLine("Changed 'cucumber' to 'green bean'")
                                   End If
                                End If
                             Next
                          End Sub ))

      ' Wait for all three tasks to complete.
      Task.WaitAll(tasks.ToArray())

      ' Display the final contents of the cache.
      Console.WriteLine()
      Console.WriteLine("Values in synchronized cache: ")
      For ctr As Integer = 1 To sc.Count
         Console.WriteLine("   {0}: {1}", ctr, sc.Read(ctr))
      Next
   End Sub
End Module
' The example displays output like the following:
'    Task 1 read 0 items:
'
'    Task 3 wrote 17 items
'
'    Task 1 read 17 items: [broccoli] [cauliflower] [carrot] [sorrel] [baby turnip] [
'    beet] [brussel sprout] [cabbage] [plantain] [spinach] [grape leaves] [lime leave
'    s] [corn] [radish] [cucumber] [raddichio] [lima beans]
'
'    Task 2 read 0 items:
'
'    Task 2 read 17 items: [lima beans] [raddichio] [cucumber] [radish] [corn] [lime
'    leaves] [grape leaves] [spinach] [plantain] [cabbage] [brussel sprout] [beet] [b
'    aby turnip] [sorrel] [carrot] [cauliflower] [broccoli]
'
'    Changed 'cucumber' to 'green bean'
'
'    Values in synchronized cache:
'       1: broccoli
'       2: cauliflower
'       3: carrot
'       4: sorrel
'       5: baby turnip
'       6: beet
'       7: brussel sprout
'       8: cabbage
'       9: plantain
'       10: spinach
'       11: grape leaves
'       12: lime leaves
'       13: corn
'       14: radish
'       15: green bean
'       16: raddichio
'       17: lima beans

Remarks

Verwenden Sie ReaderWriterLockSlim, um eine Ressource zu schützen, die von mehreren Threads gelesen und jeweils von einem Thread geschrieben wird.Use ReaderWriterLockSlim to protect a resource that is read by multiple threads and written to by one thread at a time. ReaderWriterLockSlim das zulassen, dass sich mehrere Threads im Lesemodus befinden, kann sich ein Thread im Schreibmodus mit ausschließlicher Besitz der Sperre befinden und ermöglicht es einem Thread, der über Lesezugriff verfügt, im erweiterbaren Lesemodus zu sein, von dem aus der Thread auf den Schreibmodus aktualisiert werden kann, ohne dass der Lesezugriff auf die Ressource aufgegeben werden muss.ReaderWriterLockSlim allows multiple threads to be in read mode, allows one thread to be in write mode with exclusive ownership of the lock, and allows one thread that has read access to be in upgradeable read mode, from which the thread can upgrade to write mode without having to relinquish its read access to the resource.

Note

ReaderWriterLockSlim ähnelt ReaderWriterLock, verfügt aber über vereinfachte Regeln für Rekursion sowie für Upgrade und Downgrade des Sperrstatus.ReaderWriterLockSlim is similar to ReaderWriterLock, but it has simplified rules for recursion and for upgrading and downgrading lock state. ReaderWriterLockSlim vermeidet viele potenzielle Deadlocks.ReaderWriterLockSlim avoids many cases of potential deadlock. Darüber hinaus ist die Leistung von ReaderWriterLockSlim wesentlich besser als die von ReaderWriterLock.In addition, the performance of ReaderWriterLockSlim is significantly better than ReaderWriterLock. ReaderWriterLockSlim wird für alle Neuentwicklungen empfohlen.ReaderWriterLockSlim is recommended for all new development.

Standardmäßig werden neue Instanzen von ReaderWriterLockSlim mit dem LockRecursionPolicy.NoRecursion-Flag erstellt und lassen keine Rekursion zu.By default, new instances of ReaderWriterLockSlim are created with the LockRecursionPolicy.NoRecursion flag and do not allow recursion. Diese Standard Richtlinie wird für alle neuen Entwicklungen empfohlen, da bei der Rekursion unnötige Komplikationen eingeführt werden und der Code anfälliger für Deadlocks wird.This default policy is recommended for all new development, because recursion introduces unnecessary complications and makes your code more prone to deadlocks. Um die Migration von vorhandenen Projekten zu vereinfachen, die Monitor oder ReaderWriterLockverwenden, können Sie das LockRecursionPolicy.SupportsRecursion-Flag verwenden, um Instanzen von ReaderWriterLockSlim zu erstellen, die Rekursion zulassen.To simplify migration from existing projects that use Monitor or ReaderWriterLock, you can use the LockRecursionPolicy.SupportsRecursion flag to create instances of ReaderWriterLockSlim that allow recursion.

Ein Thread kann die Sperre in drei Modi eingeben: Lesemodus, Schreibmodus und aktualisierbaren Lesemodus.A thread can enter the lock in three modes: read mode, write mode, and upgradeable read mode. (Im weiteren Verlauf dieses Themas wird "erweiterbare Lesemodus" als "erweiterbaren Modus" bezeichnet, und der Ausdruck "Enter x Mode" wird im Gegensatz zum längeren Ausdruck "Sperre in x Modus eingeben" verwendet.)(In the rest of this topic, "upgradeable read mode" is referred to as "upgradeable mode", and the phrase "enter x mode" is used in preference to the longer phrase "enter the lock in x mode".)

Unabhängig von der Rekursions Richtlinie kann sich jeweils nur ein Thread im Schreibmodus befinden.Regardless of recursion policy, only one thread can be in write mode at any time. Wenn sich ein Thread im Schreibmodus befindet, kann kein anderer Thread die Sperre in einem beliebigen Modus eingeben.When a thread is in write mode, no other thread can enter the lock in any mode. Nur ein Thread kann jederzeit im erweiterbaren Modus ausgeführt werden.Only one thread can be in upgradeable mode at any time. Eine beliebige Anzahl von Threads kann sich im Lesemodus befinden, und es kann ein Thread im erweiterbaren Modus vorhanden sein, während sich andere Threads im Lesemodus befinden.Any number of threads can be in read mode, and there can be one thread in upgradeable mode while other threads are in read mode.

Important

Dieser Typ implementiert die IDisposable-Schnittstelle.This type implements the IDisposable interface. Nach Abschluss der Verwendung sollten Sie den Typ entweder direkt oder indirekt löschen.When you have finished using the type, you should dispose of it either directly or indirectly. Zum direkten Löschen des Typs rufen Sie seine Dispose-Methode in einem try/catch-Block auf.To dispose of the type directly, call its Dispose method in a try/catch block. Zum indirekten Löschen verwenden Sie ein Sprachkonstrukt wie using (in C#) oder Using (in Visual Basic).To dispose of it indirectly, use a language construct such as using (in C#) or Using (in Visual Basic). Weitere Informationen finden Sie im Abschnitt „Verwenden eines Objekts, das IDisposable implementiert“ des Themas „Die IDisposable-Schnittstelle“.For more information, see the "Using an Object that Implements IDisposable" section in the IDisposable interface topic.

ReaderWriterLockSlim hat eine verwaltete Thread Affinität. Das heißt, dass jedes Thread Objekt seine eigenen Methodenaufrufe ausführen muss, um Sperr Modi einzugeben und zu beenden.ReaderWriterLockSlim has managed thread affinity; that is, each Thread object must make its own method calls to enter and exit lock modes. Der Modus eines anderen Threads kann von keinem Thread geändert werden.No thread can change the mode of another thread.

Wenn ein ReaderWriterLockSlim keine Rekursion zulässt, kann ein Thread, der versucht, die Sperre einzugeben, aus verschiedenen Gründen blockieren:If a ReaderWriterLockSlim does not allow recursion, a thread that tries to enter the lock can block for several reasons:

  • Ein Thread, der versucht, in den Lesemodus zu wechseln, wenn Threads darauf warten, in den Schreibmodus zu wechseln, oder wenn ein einzelner Thread im Schreibmodus vorhanden ist.A thread that tries to enter read mode blocks if there are threads waiting to enter write mode or if there is a single thread in write mode.

    Note

    Das Blockieren neuer Leser, wenn Writer in die Warteschlange eingereiht werden, ist eine Richtlinie für die Sperrung von SperrenBlocking new readers when writers are queued is a lock fairness policy that favors writers. Die aktuelle Fairness-Richtlinie gleicht die Fairness von Lesern und Writern aus, um den Durchsatz in den gängigsten Szenarien zu fördern.The current fairness policy balances fairness to readers and writers, to promote throughput in the most common scenarios. In zukünftigen Versionen der .NET Framework.NET Framework können neue Fairness-Richtlinien eingeführt werden.Future versions of the .NET Framework.NET Framework may introduce new fairness policies.

  • Ein Thread, der versucht, den erweiterbaren Modus zu wechseln, wenn sich bereits ein Thread im erweiterbaren Modus befindet, wenn Threads darauf warten, in den Schreibmodus zu wechseln, oder wenn ein einzelner Thread im Schreibmodus vorhanden ist.A thread that tries to enter upgradeable mode blocks if there is already a thread in upgradeable mode, if there are threads waiting to enter write mode, or if there is a single thread in write mode.

  • Ein Thread, der versucht, in den Schreibmodus zu wechseln, wenn ein Thread in einem der drei Modi vorhanden ist.A thread that tries to enter write mode blocks if there is a thread in any of the three modes.

Aktualisieren und Herabstufen von SperrenUpgrading and Downgrading Locks

Der aktualisierbare Modus ist für Fälle vorgesehen, in denen ein Thread normalerweise aus der geschützten Ressource liest, aber möglicherweise in ihn schreiben muss, wenn eine bestimmte Bedingung erfüllt ist.Upgradeable mode is intended for cases where a thread usually reads from the protected resource, but might need to write to it if some condition is met. Ein Thread, der einen ReaderWriterLockSlim im erweiterbaren Modus eingegeben hat, verfügt über Lesezugriff auf die geschützte Ressource und kann durch Aufrufen der Methoden EnterWriteLock oder TryEnterWriteLock auf den Schreibmodus aktualisieren.A thread that has entered a ReaderWriterLockSlim in upgradeable mode has read access to the protected resource, and can upgrade to write mode by calling the EnterWriteLock or TryEnterWriteLock methods. Da es jeweils nur einen Thread im erweiterbaren Modus geben kann, kann ein Upgrade auf den Schreibmodus nicht durchgeführt werden, wenn die Rekursion nicht zulässig ist. Dies ist die Standard Richtlinie.Because there can be only one thread in upgradeable mode at a time, upgrading to write mode cannot deadlock when recursion is not allowed, which is the default policy.

Important

Unabhängig von der Rekursions Richtlinie ist ein Thread, der anfänglich in den Lesemodus wechselt, nicht berechtigt, auf den erweiterbaren Modus oder den Schreibmodus zu aktualisieren, da dieses Muster eine hohe Wahrscheinlichkeit von Deadlocks erzeugt.Regardless of recursion policy, a thread that initially entered read mode is not allowed to upgrade to upgradeable mode or write mode, because that pattern creates a strong probability of deadlocks. Wenn z. b. zwei Threads im Lesemodus versuchen, in den Schreibmodus zu wechseln, wird ein Deadlock angezeigt.For example, if two threads in read mode both try to enter write mode, they will deadlock. Der aktualisierbare Modus ist so konzipiert, dass solche Deadlocks vermieden werden.Upgradeable mode is designed to avoid such deadlocks.

Wenn andere Threads im Lesemodus vorhanden sind, wird der Thread, der die Blöcke aktualisiert, blockiert.If there are other threads in read mode, the thread that is upgrading blocks. Während der Thread blockiert wird, werden andere Threads, die versuchen, in den Lesemodus zu wechseln, blockiert.While the thread is blocked, other threads that try to enter read mode are blocked. Wenn alle Threads vom Lesemodus beendet wurden, wechselt der blockierte aktualisierbare Thread in den Schreibmodus.When all threads have exited from read mode, the blocked upgradeable thread enters write mode. Wenn andere Threads auf den Schreibmodus warten, bleiben Sie blockiert, da der einzige Thread, der sich im erweiterbaren Modus befindet, verhindert, dass Sie exklusiven Zugriff auf die Ressource erlangen.If there are other threads waiting to enter write mode, they remain blocked, because the single thread that is in upgradeable mode prevents them from gaining exclusive access to the resource.

Wenn der Thread im erweiterbaren Modus den Schreibmodus beendet, können andere Threads, die auf die Eingabe des Lesemodus warten, dies tun, es sei denn, es sind Threads vorhanden, die auf den Schreibmodus warten.When the thread in upgradeable mode exits write mode, other threads that are waiting to enter read mode can do so, unless there are threads waiting to enter write mode. Der Thread im erweiterbaren Modus kann auf unbestimmte Zeit aktualisiert und herabgestuft werden, solange er der einzige Thread ist, der in die geschützte Ressource schreibt.The thread in upgradeable mode can upgrade and downgrade indefinitely, as long as it is the only thread that writes to the protected resource.

Important

Wenn Sie zulassen, dass mehrere Threads in den Schreibmodus oder den erweiterbaren Modus wechseln, dürfen Sie nicht zulassen, dass ein Thread den aktualisierbaren Modus monopolisiert.If you allow multiple threads to enter write mode or upgradeable mode, you must not allow one thread to monopolize upgradeable mode. Andernfalls können Threads, die versuchen, direkt in den Schreibmodus zu wechseln, unbegrenzt blockiert werden. während Sie blockiert werden, können andere Threads nicht in den Lesemodus wechseln.Otherwise, threads that try to enter write mode directly will be blocked indefinitely, and while they are blocked, other threads will be unable to enter read mode.

Ein Thread im erweiterbaren Modus kann in den Lesemodus herabgestuft werden, indem zuerst die EnterReadLock-Methode aufgerufen und dann die ExitUpgradeableReadLock-Methode aufgerufen wird.A thread in upgradeable mode can downgrade to read mode by first calling the EnterReadLock method and then calling the ExitUpgradeableReadLock method. Dieses Downgrade-Muster ist für alle Sperr Rekursions Richtlinien zulässig, auch NoRecursion.This downgrade pattern is allowed for all lock recursion policies, even NoRecursion.

Nach dem Downgrade in den Lesemodus kann ein Thread den erweiterbaren Modus erst wieder eingeben, wenn er vom Lesemodus beendet wurde.After downgrading to read mode, a thread cannot reenter upgradeable mode until it has exited from read mode.

Rekursiv Eingabe der SperreEntering the Lock Recursively

Sie können einen ReaderWriterLockSlim erstellen, der einen rekursiven Sperr Eintrag unterstützt, indem Sie den ReaderWriterLockSlim(LockRecursionPolicy)-Konstruktor verwenden, der Sperr Richtlinien angibt, und LockRecursionPolicy.SupportsRecursionangeben.You can create a ReaderWriterLockSlim that supports recursive lock entry by using the ReaderWriterLockSlim(LockRecursionPolicy) constructor that specifies lock policy, and specifying LockRecursionPolicy.SupportsRecursion.

Note

Die Verwendung von Rekursion ist für die neue Entwicklung nicht empfehlenswert, da dadurch unnötige Komplikationen eingeführt werden und der Code anfälliger für Deadlocks wird.The use of recursion is not recommended for new development, because it introduces unnecessary complications and makes your code more prone to deadlocks.

Für eine ReaderWriterLockSlim, die Rekursion zulässt, kann Folgendes über die Modi, die ein Thread eingegeben werden kann, aufgeführt werden:For a ReaderWriterLockSlim that allows recursion, the following can be said about the modes a thread can enter:

  • Ein Thread im Lesemodus kann rekursiv in den Lesemodus wechseln, kann jedoch nicht in den Schreibmodus oder den erweiterbaren Modus wechseln.A thread in read mode can enter read mode recursively, but cannot enter write mode or upgradeable mode. Wenn Sie versucht, dies zu tun, wird eine LockRecursionException ausgelöst.If it tries to do this, a LockRecursionException is thrown. Wenn Sie in den Lesemodus wechseln und dann in den Schreibmodus oder den erweiterbaren Modus wechseln, handelt es sich um ein Muster mit einer starken Wahrscheinlichkeit von Deadlocks, sodass es nicht zulässig ist.Entering read mode and then entering write mode or upgradeable mode is a pattern with a strong probability of deadlocks, so it is not allowed. Wie bereits erwähnt, wird der erweiterbare Modus für Fälle bereitgestellt, in denen es erforderlich ist, eine Sperre zu aktualisieren.As discussed earlier, upgradeable mode is provided for cases where it is necessary to upgrade a lock.

  • Ein Thread im erweiterbaren Modus kann in den Schreibmodus und/oder den Lesemodus wechseln und jeden der drei Modi rekursiv eingeben.A thread in upgradeable mode can enter write mode and/or read mode, and can enter any of the three modes recursively. Der Versuch, in den Schreibmodus einzutreten, blockiert jedoch, wenn andere Threads im Lesemodus vorhanden sind.However, an attempt to enter write mode blocks if there are other threads in read mode.

  • Ein Thread im Schreibmodus kann in den Lesemodus und/oder den aktualisierbaren Modus wechseln und jeden der drei Modi rekursiv eingeben.A thread in write mode can enter read mode and/or upgradeable mode, and can enter any of the three modes recursively.

  • Ein Thread, der nicht die Sperre eingegeben hat, kann einen beliebigen Modus eingeben.A thread that has not entered the lock can enter any mode. Dieser Versuch kann aus denselben Gründen blockiert werden, wenn versucht wird, eine nicht rekursive Sperre einzugeben.This attempt can block for the same reasons as an attempt to enter a non-recursive lock.

Ein Thread kann die Modi beenden, die er in beliebiger Reihenfolge eingegeben hat, solange er jeden Modus genau so oft verlässt, wie er in diesen Modus wechselt.A thread can exit the modes it has entered in any order, as long as it exits each mode exactly as many times as it entered that mode. Wenn ein Thread versucht, den Modus zu häufig zu beenden oder einen Modus zu beenden, der nicht eingegeben wurde, wird eine SynchronizationLockException ausgelöst.If a thread tries to exit a mode too many times, or to exit a mode it has not entered, a SynchronizationLockException is thrown.

Sperr ZuständeLock States

Möglicherweise ist es hilfreich, sich die Sperre in Bezug auf ihre Zustände vorzustellen.You may find it useful to think of the lock in terms of its states. Eine ReaderWriterLockSlim kann einen von vier Zuständen aufweisen: nicht eingegeben, lesen, aktualisieren und schreiben.A ReaderWriterLockSlim can be in one of four states: not entered, read, upgrade, and write.

  • Nicht eingegeben: in diesem Zustand haben keine Threads die Sperre eingegeben (oder alle Threads haben die Sperre verlassen).Not entered: In this state, no threads have entered the lock (or all threads have exited the lock).

  • Read: in diesem Zustand hat mindestens ein Thread die Sperre für den Lesezugriff auf die geschützte Ressource erreicht.Read: In this state, one or more threads have entered the lock for read access to the protected resource.

    Note

    Ein Thread kann die Sperre im Lesemodus mithilfe der Methoden EnterReadLock oder TryEnterReadLock oder durch Herabstufen des erweiterbaren Modus eingeben.A thread can enter the lock in read mode by using the EnterReadLock or TryEnterReadLock methods, or by downgrading from upgradeable mode.

  • Upgrade: in diesem Zustand hat ein Thread die Sperre für den Lesezugriff mit der Option zum Aktualisieren auf Schreibzugriff (d. h. im erweiterbaren Modus) und NULL oder mehr Threads in die Sperre für den Lesezugriff eingegeben.Upgrade: In this state, one thread has entered the lock for read access with the option to upgrade to write access (that is, in upgradeable mode), and zero or more threads have entered the lock for read access. Es kann nicht mehr als ein Thread gleichzeitig die Sperre mit der Option zum Aktualisieren eingeben. zusätzliche Threads, die versuchen, den erweiterbaren Modus einzugeben, werden blockiert.No more than one thread at a time can enter the lock with the option to upgrade; additional threads that try to enter upgradeable mode are blocked.

  • Write: in diesem Zustand hat ein Thread die Sperre für Schreibzugriff auf die geschützte Ressource eingegeben.Write: In this state, one thread has entered the lock for write access to the protected resource. Dieser Thread besitzt exklusiven Besitz der Sperre.That thread has exclusive possession of the lock. Jeder andere Thread, der versucht, die Sperre aus irgendeinem Grund einzugeben, wird blockiert.Any other thread that tries to enter the lock for any reason is blocked.

In der folgenden Tabelle werden die Übergänge zwischen Sperr Zuständen für Sperren beschrieben, die keine Rekursion zulassen, wenn ein Thread t die in der Spalte ganz links beschriebene Aktion übernimmt.The following table describes the transitions between lock states, for locks that do not allow recursion, when a thread t takes the action described in the leftmost column. Zu dem Zeitpunkt, an dem die Aktion ausgeführt wird, hat t keinen Modus.At the time it takes the action, t has no mode. (Der Sonderfall, in dem sich t im erweiterbaren Modus befindet, wird in den Tabellen Fußnoten beschrieben.) Die obere Zeile beschreibt den Anfangszustand der Sperre.(The special case where t is in upgradeable mode is described in the table footnotes.) The top row describes the starting state of the lock. Die Zellen beschreiben, was mit dem Thread geschieht, und zeigen Änderungen am Sperr Zustand in Klammern an.The cells describe what happens to the thread, and show changes to the lock state in parentheses.

Nicht eingegeben (N)Not entered (N) Lesen (Read, R)Read (R) Upgrade (U)Upgrade (U) Schreiben (Write, W)Write (W)
t in den Lesemodust enters read mode t in den Einzug (R).t enters (R). t blockiert, wenn Threads auf den Schreibmodus warten. Andernfalls t in den Einzug.t blocks if threads are waiting for write mode; otherwise, t enters. t blockiert, wenn Threads auf den Schreibmodus warten. Andernfalls t in den Einzug. 1t blocks if threads are waiting for write mode; otherwise, t enters.1 t Blöcke.t blocks.
t wechselt in den upgradefähigen Modus.t enters upgradeable mode t Enter (U).t enters (U). t blockiert, wenn Threads auf den Schreibmodus oder den Upgrademodus warten. Andernfalls t in den Einzug (U).t blocks if threads are waiting for write mode or upgrade mode; otherwise, t enters (U). t Blöcke.t blocks. t Blöcke.t blocks.
t in den Schreibmodust enters write mode t in den Einzug (W).t enters (W). t Blöcke.t blocks. t Blöcke. 2t blocks.2 t Blöcke.t blocks.

1 wenn t im erweiterbaren Modus gestartet wird, wechselt er in den Lesemodus.1 If t starts out in upgradeable mode, it enters read mode. Diese Aktion blockiert nie.This action never blocks. Der Sperr Zustand ändert sich nicht.The lock state does not change. (Der Thread kann dann einen Downgrade in den Lesemodus vervollständigen, indem er den aktualisierbaren Modus verlässt.)(The thread can then complete a downgrade to read mode by exiting upgradeable mode.)

2 wenn t im erweiterbaren Modus gestartet wird, wird blockiert, wenn Threads im Lesemodus vorhanden sind.2 If t starts out in upgradeable mode, it blocks if there are threads in read mode. Andernfalls wird ein Upgrade auf den Schreibmodus ausgeführt.Otherwise it upgrades to write mode. Der Sperr Status ändert sich in Write (W).The lock state changes to Write (W). Wenn t blockiert, weil Threads im Lesemodus vorhanden sind, wird der Schreibmodus in den Schreibmodus eingefügt, sobald der letzte Thread den Lesemodus beendet, auch wenn Threads vorhanden sind, die auf den Schreibmodus warten.If t blocks because there are threads in read mode, it enters write mode as soon as the last thread exits read mode, even if there are threads waiting to enter write mode.

Wenn eine Zustandsänderung auftritt, weil ein Thread die Sperre beendet, wird der nächste zu erwachende Thread wie folgt ausgewählt:When a state change occurs because a thread exits the lock, the next thread to be awakened is selected as follows:

  • Zuerst ein Thread, der auf den Schreibmodus wartet und sich bereits im erweiterbaren Modus befindet (es kann höchstens ein solcher Thread vorhanden sein).First, a thread that is waiting for write mode and is already in upgradeable mode (there can be at most one such thread).

  • Ein Fehler, ein Thread, der auf den Schreibmodus wartet.Failing that, a thread that is waiting for write mode.

  • Wenn ein Fehler auftritt, ein Thread, der auf den erweiterbaren Modus wartet.Failing that, a thread that is waiting for upgradeable mode.

  • Wenn ein Fehler aufgetreten ist, alle Threads, die auf den Lesemodus warten.Failing that, all threads that are waiting for read mode.

Der nachfolgende Status der Sperre lautet in den ersten beiden Fällen immer Write (W) und das Upgrade (U) im dritten Fall, unabhängig vom Status der Sperre, wenn der Ende Thread die Zustandsänderung ausgelöst hat.The subsequent state of the lock is always Write (W) in the first two cases and Upgrade (U) in the third case, regardless of the state of the lock when the exiting thread triggered the state change. Im letzten Fall lautet der Status der Sperre Upgrade (U), wenn sich nach der Zustandsänderung ein Thread im erweiterbaren Modus befindet, und andernfalls der Lesevorgang (R), unabhängig vom vorherigen Zustand.In the last case, the state of the lock is Upgrade (U) if there is a thread in upgradeable mode after the state change, and Read (R) otherwise, regardless of the prior state.

Constructors

ReaderWriterLockSlim()

Initialisiert eine neue Instanz der ReaderWriterLockSlim-Klasse mit Standardeigenschaftswerten.Initializes a new instance of the ReaderWriterLockSlim class with default property values.

ReaderWriterLockSlim(LockRecursionPolicy)

Initialisiert eine neue Instanz der ReaderWriterLockSlim-Klasse unter Angabe der Rekursionsrichtlinie für die Sperre.Initializes a new instance of the ReaderWriterLockSlim class, specifying the lock recursion policy.

Properties

CurrentReadCount

Ruft die Gesamtzahl von eindeutigen Threads ab, denen die Sperre im Lesemodus zugewiesen ist.Gets the total number of unique threads that have entered the lock in read mode.

IsReadLockHeld

Ruft einen Wert ab, der angibt, ob die Sperre dem aktuellen Thread im Lesemodus zugewiesen ist.Gets a value that indicates whether the current thread has entered the lock in read mode.

IsUpgradeableReadLockHeld

Ruft einen Wert ab, der angibt, ob die Sperre dem aktuellen Thread im erweiterbaren Modus zugewiesen ist.Gets a value that indicates whether the current thread has entered the lock in upgradeable mode.

IsWriteLockHeld

Ruft einen Wert ab, der angibt, ob die Sperre dem aktuellen Thread im Schreibmodus zugewiesen ist.Gets a value that indicates whether the current thread has entered the lock in write mode.

RecursionPolicy

Ruft einen Wert ab, der die Rekursionsrichtlinie für das aktuelle ReaderWriterLockSlim-Objekt angibt.Gets a value that indicates the recursion policy for the current ReaderWriterLockSlim object.

RecursiveReadCount

Ruft einen Wert ab, der als Indikator für eine Rekursion angibt, wie oft dem aktuellen Thread die Sperre im Lesemodus zugewiesen ist.Gets the number of times the current thread has entered the lock in read mode, as an indication of recursion.

RecursiveUpgradeCount

Ruft einen Wert ab, der als Indikator für eine Rekursion angibt, wie oft dem aktuellen Thread die Sperre im erweiterbaren Modus zugewiesen ist.Gets the number of times the current thread has entered the lock in upgradeable mode, as an indication of recursion.

RecursiveWriteCount

Ruft einen Wert ab, der als Indikator für eine Rekursion angibt, wie oft dem aktuellen Thread die Sperre im Schreibmodus zugewiesen ist.Gets the number of times the current thread has entered the lock in write mode, as an indication of recursion.

WaitingReadCount

Ruft die Gesamtzahl von Threads ab, die auf eine Zuweisung der Sperre im Lesemodus warten.Gets the total number of threads that are waiting to enter the lock in read mode.

WaitingUpgradeCount

Ruft die Gesamtzahl von Threads ab, die auf eine Zuweisung der Sperre im erweiterbaren Modus warten.Gets the total number of threads that are waiting to enter the lock in upgradeable mode.

WaitingWriteCount

Ruft die Gesamtzahl von Threads ab, die auf eine Zuweisung der Sperre im Schreibmodus warten.Gets the total number of threads that are waiting to enter the lock in write mode.

Methods

Dispose()

Gibt alle von der aktuellen Instanz der ReaderWriterLockSlim-Klasse verwendeten Ressourcen frei.Releases all resources used by the current instance of the ReaderWriterLockSlim class.

EnterReadLock()

Versucht, die Sperre im Lesemodus zu erhalten.Tries to enter the lock in read mode.

EnterUpgradeableReadLock()

Versucht, die Sperre im erweiterbaren Modus zu erhalten.Tries to enter the lock in upgradeable mode.

EnterWriteLock()

Versucht, die Sperre im Schreibmodus zu erhalten.Tries to enter the lock in write mode.

Equals(Object)

Bestimmt, ob das angegebene Objekt mit dem aktuellen Objekt identisch ist.Determines whether the specified object is equal to the current object.

(Inherited from Object)
ExitReadLock()

Verringert die Rekursionszahl für den Lesemodus und beendet den Lesemodus, wenn das Rekursionsergebnis 0 (null) ist.Reduces the recursion count for read mode, and exits read mode if the resulting count is 0 (zero).

ExitUpgradeableReadLock()

Verringert die Rekursionszahl für den erweiterbaren Modus und beendet den erweiterbaren Modus, wenn das Rekursionsergebnis 0 (null) ist.Reduces the recursion count for upgradeable mode, and exits upgradeable mode if the resulting count is 0 (zero).

ExitWriteLock()

Verringert die Rekursionszahl für den Schreibmodus und beendet den Schreibmodus, wenn das Rekursionsergebnis 0 (null) ist.Reduces the recursion count for write mode, and exits write mode if the resulting count is 0 (zero).

GetHashCode()

Fungiert als Standardhashfunktion.Serves as the default hash function.

(Inherited from Object)
GetType()

Ruft den Type der aktuellen Instanz ab.Gets the Type of the current instance.

(Inherited from Object)
MemberwiseClone()

Erstellt eine flache Kopie des aktuellen Object.Creates a shallow copy of the current Object.

(Inherited from Object)
ToString()

Gibt eine Zeichenfolge zurück, die das aktuelle Objekt darstellt.Returns a string that represents the current object.

(Inherited from Object)
TryEnterReadLock(Int32)

Versucht, die Sperre im Lesemodus zu erhalten. Optional wird ein ganzzahliger Timeout berücksichtigt.Tries to enter the lock in read mode, with an optional integer time-out.

TryEnterReadLock(TimeSpan)

Versucht, die Sperre im Lesemodus zu erhalten. Optional wird ein Timeout berücksichtigt.Tries to enter the lock in read mode, with an optional time-out.

TryEnterUpgradeableReadLock(Int32)

Versucht, die Sperre im erweiterbaren Modus zu erhalten. Optional wird ein Timeout berücksichtigt.Tries to enter the lock in upgradeable mode, with an optional time-out.

TryEnterUpgradeableReadLock(TimeSpan)

Versucht, die Sperre im erweiterbaren Modus zu erhalten. Optional wird ein Timeout berücksichtigt.Tries to enter the lock in upgradeable mode, with an optional time-out.

TryEnterWriteLock(Int32)

Versucht, die Sperre im Schreibmodus zu erhalten. Optional wird ein Timeout berücksichtigt.Tries to enter the lock in write mode, with an optional time-out.

TryEnterWriteLock(TimeSpan)

Versucht, die Sperre im Schreibmodus zu erhalten. Optional wird ein Timeout berücksichtigt.Tries to enter the lock in write mode, with an optional time-out.

Applies to

Thread Safety

Dieser Typ ist threadsicher.This type is thread safe.