ReaderWriterLockSlim ReaderWriterLockSlim ReaderWriterLockSlim ReaderWriterLockSlim Class

Definizione

Rappresenta un blocco che viene usato per gestire l'accesso a una risorsa, consentendo più thread per la lettura o l'accesso esclusivo per la scrittura.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
Ereditarietà
ReaderWriterLockSlimReaderWriterLockSlimReaderWriterLockSlimReaderWriterLockSlim
Implementazioni

Esempi

L'esempio seguente illustra una semplice cache sincronizzata che contiene le stringhe con chiavi di interi.The following example shows a simple synchronized cache that holds strings with integer keys. Un'istanza di ReaderWriterLockSlim utilizzato per sincronizzare l'accesso al Dictionary<TKey,TValue> che funge da cache interna.An instance of ReaderWriterLockSlim is used to synchronize access to the Dictionary<TKey,TValue> that serves as the inner cache.

L'esempio include metodi semplici per aggiungere alla cache, eliminare dalla cache e leggere dalla cache.The example includes simple methods to add to the cache, delete from the cache, and read from the cache. Per illustrare i timeout, l'esempio include un metodo che viene aggiunto alla cache solo se è possibile eseguire questa operazione all'interno di un timeout specificato.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.

Per illustrare la modalità aggiornabile, l'esempio include un metodo che recupera il valore associato alla chiave e lo confronta con un nuovo valore.To demonstrate upgradeable mode, the example includes a method that retrieves the value associated with a key and compares it with a new value. Se il valore viene modificato, il metodo restituisce uno stato che indica nessuna modifica.If the value is unchanged, the method returns a status indicating no change. Se viene trovato alcun valore per la chiave, viene inserita la coppia chiave/valore.If no value is found for the key, the key/value pair is inserted. Se il valore è stato modificato, viene aggiornata.If the value has changed, it is updated. La modalità aggiornabile consente al thread di eseguire l'aggiornamento da accesso in lettura per l'accesso in scrittura in base alle necessità, senza il rischio di deadlock.Upgradeable mode allows the thread to upgrade from read access to write access as needed, without the risk of deadlocks.

L'esempio include un'enumerazione annidata che consente di specificare i valori restituiti per il metodo che illustra la modalità aggiornabile.The example includes a nested enumeration that specifies the return values for the method that demonstrates upgradeable mode.

L'esempio Usa il costruttore predefinito per creare il blocco, in modo che non è consentita la ricorsione.The example uses the default constructor to create the lock, so recursion is not allowed. Programmazione di ReaderWriterLockSlim è più semplice e meno soggetta a errori quando il blocco non supporta la ricorsione.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

Il codice seguente usa quindi il SynchronizedCache oggetto usato per archiviare un dizionario di nomi vegetali.The following code then uses the SynchronizedCache object to store a dictionary of vegetable names. Crea tre attività.It creates three tasks. Il primo vengono scritti i nomi di verdure archiviate in una matrice a un SynchronizedCache istanza.The first writes the names of vegetables stored in an array to a SynchronizedCache instance. La seconda e terza attività visualizzare i nomi di verdura, il primo in modo crescente (da bassa indice in indice elevata), la seconda in ordine decrescente.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. L'attività finale cerca la stringa "cucumber" e, quando la trova, chiama il EnterUpgradeableReadLock metodo per sostituire la stringa "verde bean".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

Commenti

Usare ReaderWriterLockSlim per proteggere una risorsa che viene letta da più thread e scritta da un solo thread alla volta.Use ReaderWriterLockSlim to protect a resource that is read by multiple threads and written to by one thread at a time. ReaderWriterLockSlim consente a più thread essere in modalità di lettura, consente a un solo thread essere in modalità di scrittura con la proprietà esclusiva del blocco e consente a un thread che ha accesso in lettura sia in modalità di lettura aggiornabile, da cui il thread può eseguire l'aggiornamento alla modalità di scrittura senza la necessità di lasciare lo s accesso in lettura alla risorsa.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.

Nota

ReaderWriterLockSlim è simile a ReaderWriterLock, ma include regole semplificate per la ricorsione e per l'aggiornamento e il downgrade dello stato del blocco.ReaderWriterLockSlim is similar to ReaderWriterLock, but it has simplified rules for recursion and for upgrading and downgrading lock state. ReaderWriterLockSlim evita molti casi di deadlock potenziale.ReaderWriterLockSlim avoids many cases of potential deadlock. Inoltre, le prestazioni di ReaderWriterLockSlim sono significativamente migliori di ReaderWriterLock.In addition, the performance of ReaderWriterLockSlim is significantly better than ReaderWriterLock. ReaderWriterLockSlim è consigliato per tutte le nuove fasi di sviluppo.ReaderWriterLockSlim is recommended for all new development.

Per impostazione predefinita, le nuove istanze di ReaderWriterLockSlim vengono creati con la LockRecursionPolicy.NoRecursion flag e non consentono la ricorsione.By default, new instances of ReaderWriterLockSlim are created with the LockRecursionPolicy.NoRecursion flag and do not allow recursion. Il criterio predefinito è consigliato per tutti i nuovi progetti di sviluppo, poiché la ricorsione introduce complicazioni non necessari e rende il codice più soggette a deadlock.This default policy is recommended for all new development, because recursion introduces unnecessary complications and makes your code more prone to deadlocks. Per semplificare la migrazione da esistente i progetti che usano Monitor oppure ReaderWriterLock, è possibile utilizzare il LockRecursionPolicy.SupportsRecursion flag per creare istanze di ReaderWriterLockSlim che consentono la ricorsione.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.

Un thread può accedere al blocco in tre modalità: lettura modalità, modalità di scrittura e modalità di lettura aggiornabile.A thread can enter the lock in three modes: read mode, write mode, and upgradeable read mode. (Nella parte restante di questo argomento, "modalità di lettura aggiornabile" fa riferimento come "modalità aggiornabile" e la frase "immettere x modalità" viene usato preferita la frase più lunga "Immettere il blocco in x modalità".)(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".)

Indipendentemente dai criteri di ricorsione, solo un thread può essere in modalità di scrittura in qualsiasi momento.Regardless of recursion policy, only one thread can be in write mode at any time. Quando un thread è in modalità scrittura, nessun altro thread può accedere al blocco in qualsiasi modalità.When a thread is in write mode, no other thread can enter the lock in any mode. Solo un thread può essere in modalità aggiornabile in qualsiasi momento.Only one thread can be in upgradeable mode at any time. Qualsiasi numero di thread può essere in modalità di lettura e può esistere un solo thread in modalità aggiornabile mentre altri thread sono in modalità lettura.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.

Importante

Questo tipo implementa la IDisposable interfaccia.This type implements the IDisposable interface. Dopo aver utilizzato il tipo, è necessario eliminarlo direttamente o indirettamente.When you have finished using the type, you should dispose of it either directly or indirectly. Per eliminare il tipo direttamente, chiamare relativi Dispose metodo in un try / catch blocco.To dispose of the type directly, call its Dispose method in a try/catch block. Per eliminarlo indirettamente, utilizzare un costrutto di linguaggio come ad esempio using in C# o Using in Visual Basic.To dispose of it indirectly, use a language construct such as using (in C#) or Using (in Visual Basic). Per altre informazioni, vedere la sezione "Utilizzo di oggetti che implementano IDisposable" nel IDisposable argomento relativo all'interfaccia.For more information, see the "Using an Object that Implements IDisposable" section in the IDisposable interface topic.

ReaderWriterLockSlim ha gestito l'affinità di thread; vale a dire, ognuna Thread oggetto deve eseguire la propria chiamate di metodo per attivare e disattivare la modalità di blocco.ReaderWriterLockSlim has managed thread affinity; that is, each Thread object must make its own method calls to enter and exit lock modes. Nessun thread può modificare la modalità di un altro thread.No thread can change the mode of another thread.

Se un ReaderWriterLockSlim non supporta la ricorsione, un thread che prova ad attivare il blocco può essere bloccato per diversi motivi:If a ReaderWriterLockSlim does not allow recursion, a thread that tries to enter the lock can block for several reasons:

  • Un thread che prova ad attivare la modalità lettura blocchi se sono presenti thread in attesa di immettere la modalità scrittura o è presente un singolo thread in modalità di scrittura.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.

    Nota

    Blocchi i lettori di nuovo quando vengono messe in coda i writer è un criterio di equità di blocco che predilige i thread.Blocking new readers when writers are queued is a lock fairness policy that favors writers. I criteri di equità correnti bilanciano equità tra i lettori e writer, per aumentare la velocità effettiva in scenari più comuni.The current fairness policy balances fairness to readers and writers, to promote throughput in the most common scenarios. Le versioni future del .NET Framework.NET Framework può introdurre nuovi criteri di equità.Future versions of the .NET Framework.NET Framework may introduce new fairness policies.

  • Un thread che prova ad attivare i blocchi alla modalità aggiornabile se esiste già un thread in modalità aggiornabile, se sono presenti thread in attesa di attivazione della modalità scrittura, o se è presente un singolo thread in modalità di scrittura.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.

  • Un thread che prova ad attivare i blocchi in modalità scrittura se è presente un thread in una qualsiasi delle tre modalità.A thread that tries to enter write mode blocks if there is a thread in any of the three modes.

Blocchi di aggiornamento e downgradeUpgrading and Downgrading Locks

La modalità aggiornabile è destinata ai casi in cui un thread in genere legge da risorsa protetta, ma potrebbe essere necessario per la scrittura se vengono soddisfatte determinate condizioni.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. Un thread entrato in un ReaderWriterLockSlim in modalità aggiornabile con accesso in lettura alla risorsa protetta e può essere aggiornato alla modalità di scrittura chiamando il EnterWriteLock o TryEnterWriteLock metodi.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. Poiché può esserci un solo thread in modalità aggiornabile in una fase, l'aggiornamento alla modalità di scrittura non è possibile deadlock durante la ricorsione non è consentita, ovvero i criteri predefiniti.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.

Importante

Indipendentemente dai criteri di ricorsione, un thread che ha inizialmente acceduto leggere in modalità non è consentita l'aggiornamento alla modalità aggiornabile o modalità scrittura, perché ciò comporterebbe una forte probabilità di deadlock.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. Ad esempio, se due thread in modalità lettura che entrambi tentano di accedere alla modalità di scrittura, provocano un deadlock.For example, if two threads in read mode both try to enter write mode, they will deadlock. La modalità aggiornabile è progettata per evitare deadlock di questo tipo.Upgradeable mode is designed to avoid such deadlocks.

Se sono presenti altri thread in modalità di lettura, il thread che sta eseguendo l'aggiornamento di blocchi.If there are other threads in read mode, the thread that is upgrading blocks. Mentre il thread è bloccato, altri thread che tentano di accedere alla modalità di lettura vengono bloccate.While the thread is blocked, other threads that try to enter read mode are blocked. Quando tutti i thread sono usciti dalla modalità di lettura, il thread bloccato aggiornabile passa alla modalità di scrittura.When all threads have exited from read mode, the blocked upgradeable thread enters write mode. Se sono presenti altri thread in attesa di immettere la modalità scrittura, rimangono bloccati, perché il thread singolo che si trova in modalità aggiornabile impedisce loro di ottenere accesso esclusivo alla risorsa.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.

Quando il thread in modalità aggiornabile esce dalla modalità di scrittura, altri thread in attesa di attivare la modalità di lettura possono farlo, a meno che non sono presenti thread in attesa di immettere la modalità scrittura.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. Il thread in modalità aggiornabile può eseguire l'aggiornamento e il downgrade a tempo indeterminato, purché è il thread che scrive alla risorsa protetta.The thread in upgradeable mode can upgrade and downgrade indefinitely, as long as it is the only thread that writes to the protected resource.

Importante

Se si consente a più thread immettere modalità di scrittura o la modalità aggiornabile, che non è necessario consentire un solo thread monopolizza modalità aggiornabile.If you allow multiple threads to enter write mode or upgradeable mode, you must not allow one thread to monopolize upgradeable mode. In caso contrario, i thread che tentano di accedere in scrittura modalità direttamente verrà bloccata per un periodo illimitato e mentre sono bloccati, altri thread sarà in grado di attivare la modalità di lettura.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.

Possa effettuare il downgrade di un thread in modalità aggiornabile per la modalità lettura chiamando prima il EnterReadLock metodo e chiamando quindi il ExitUpgradeableReadLock (metodo).A thread in upgradeable mode can downgrade to read mode by first calling the EnterReadLock method and then calling the ExitUpgradeableReadLock method. Questo modello il downgrade è consentito anche per tutti i criteri di ricorsione di blocco, NoRecursion.This downgrade pattern is allowed for all lock recursion policies, even NoRecursion.

Dopo il downgrade alla modalità di lettura, un thread non è possibile immettere nuovamente la modalità aggiornabile fino a quando non è stato terminato dalla modalità di lettura.After downgrading to read mode, a thread cannot reenter upgradeable mode until it has exited from read mode.

Immettere il blocco in modo ricorsivoEntering the Lock Recursively

È possibile creare un ReaderWriterLockSlim che supporta l'immissione di blocco ricorsiva tramite il ReaderWriterLockSlim(LockRecursionPolicy) costruttore che consente di specificare criteri di blocco e specificando LockRecursionPolicy.SupportsRecursion.You can create a ReaderWriterLockSlim that supports recursive lock entry by using the ReaderWriterLockSlim(LockRecursionPolicy) constructor that specifies lock policy, and specifying LockRecursionPolicy.SupportsRecursion.

Nota

L'uso di ricorsione non è consigliabile per i nuovi sviluppi, in quanto introduce complessità non necessarie e rende il codice più soggette a deadlock.The use of recursion is not recommended for new development, because it introduces unnecessary complications and makes your code more prone to deadlocks.

Per un ReaderWriterLockSlim che consente la ricorsione, si possono affermare seguenti sulle modalità di un thread può accedere:For a ReaderWriterLockSlim that allows recursion, the following can be said about the modes a thread can enter:

  • Un thread in modalità di lettura possa accedere in modo ricorsivo modalità lettura, ma non è possibile immettere la modalità scrittura o in modalità aggiornabile.A thread in read mode can enter read mode recursively, but cannot enter write mode or upgradeable mode. Se tenta di eseguire questa operazione, un LockRecursionException viene generata un'eccezione.If it tries to do this, a LockRecursionException is thrown. Immissione di leggere la modalità e immettendo quindi la modalità scrittura o la modalità aggiornabile è un modello con una forte probabilità di deadlock, in modo che non è consentito.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. Come illustrato in precedenza, la modalità aggiornabile viene fornita per i casi in cui è necessario un blocco di aggiornamento.As discussed earlier, upgradeable mode is provided for cases where it is necessary to upgrade a lock.

  • Un thread in modalità aggiornabile possibile immettere la modalità di scrittura e/o modalità di lettura e può accedere a ognuna le tre modalità ricorsiva.A thread in upgradeable mode can enter write mode and/or read mode, and can enter any of the three modes recursively. Tuttavia, un tentativo di immettere scrivere modalità blocchi se sono presenti altri thread in modalità lettura.However, an attempt to enter write mode blocks if there are other threads in read mode.

  • Un thread in modalità di scrittura può immettere la modalità lettura e/o la modalità aggiornabile e possibile immettere qualsiasi in modo ricorsivo le tre modalità.A thread in write mode can enter read mode and/or upgradeable mode, and can enter any of the three modes recursively.

  • Un thread che non ha acceduto al blocco è possibile immettere qualsiasi modalità.A thread that has not entered the lock can enter any mode. Questo tentativo può essere bloccato per gli stessi motivi un tentativo di attivare un blocco di non ricorsiva.This attempt can block for the same reasons as an attempt to enter a non-recursive lock.

Un thread può uscire le modalità che è stato attivato in qualsiasi ordine, purché si conclude ogni modalità esattamente come tutte le volte che passato in tale modalità.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. Se un thread prova a uscire da una modalità troppe volte o per uscire da una modalità non ha acceduto, un SynchronizationLockException viene generata un'eccezione.If a thread tries to exit a mode too many times, or to exit a mode it has not entered, a SynchronizationLockException is thrown.

Stati di bloccoLock States

Potrebbe essere utile sapere che il blocco in termini di stati.You may find it useful to think of the lock in terms of its states. Oggetto ReaderWriterLockSlim può trovarsi in uno dei quattro stati: non immesso, lettura, aggiornamento e scrittura.A ReaderWriterLockSlim can be in one of four states: not entered, read, upgrade, and write.

  • Non è stato immesso: In questo stato, nessun thread ha acceduto al blocco oppure tutti i thread sono usciti dal blocco.Not entered: In this state, no threads have entered the lock (or all threads have exited the lock).

  • Lettura consigliata: In questo stato, uno o più thread hanno acceduto al blocco per l'accesso in lettura alla risorsa protetta.Read: In this state, one or more threads have entered the lock for read access to the protected resource.

    Nota

    Un thread può accedere al blocco in modalità di lettura usando il EnterReadLock o TryEnterReadLock metodi, o il downgrade dalla modalità aggiornabile.A thread can enter the lock in read mode by using the EnterReadLock or TryEnterReadLock methods, or by downgrading from upgradeable mode.

  • Eseguire l'aggiornamento: In questo stato, un thread ha acceduto al blocco per l'accesso in lettura con la possibilità di eseguire l'aggiornamento per l'accesso in scrittura (vale a dire, in modalità aggiornabile), e zero o più thread hanno acceduto al blocco per l'accesso in lettura.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. Non più di un thread alla volta può attivare il blocco con l'opzione per aggiornare; gli altri thread che tenta di accedere alla modalità aggiornabile vengono bloccate.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.

  • Scrittura: In questo stato, un thread ha acceduto al blocco per l'accesso in scrittura alla risorsa protetta.Write: In this state, one thread has entered the lock for write access to the protected resource. Thread in questione sia esclusivo proprietaria del blocco.That thread has exclusive possession of the lock. Un altro thread che prova ad attivare il blocco per qualsiasi motivo è bloccato.Any other thread that tries to enter the lock for any reason is blocked.

La tabella seguente descrive le transizioni tra stati di blocco, per i blocchi che non consentono la ricorsione, quando un thread t accetta l'azione descritta nella colonna più a sinistra.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. Al momento accetta l'azione, t non possiede alcuna modalità.At the time it takes the action, t has no mode. (Il caso speciale in cui t è in modalità aggiornabile è descritto nel piè di pagina di tabella.) La prima riga descrive lo stato inizio del blocco.(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. Le celle viene descritto cosa succede al thread e visualizzare le modifiche apportate allo stato di blocco tra parentesi.The cells describe what happens to the thread, and show changes to the lock state in parentheses.

Nessun accesso (N)Not entered (N) Read (R)Read (R) Aggiornamento (U)Upgrade (U) Scrittura (S)Write (W)
t passa alla modalità di letturat enters read mode t assume (R).t enters (R). t blocchi se sono thread in attesa per la modalità scrittura; in caso contrario, t immette.t blocks if threads are waiting for write mode; otherwise, t enters. t blocchi se sono thread in attesa per la modalità scrittura; in caso contrario, t immette. 1t blocks if threads are waiting for write mode; otherwise, t enters.1 t blocchi.t blocks.
t passa alla modalità aggiornabilet enters upgradeable mode t assume (U).t enters (U). t blocchi se sono thread in attesa per la modalità di scrittura o la modalità di aggiornamento; in caso contrario, t immette (U).t blocks if threads are waiting for write mode or upgrade mode; otherwise, t enters (U). t blocchi.t blocks. t blocchi.t blocks.
t passa alla modalità di scritturat enters write mode t immette (W).t enters (W). t blocchi.t blocks. t blocchi. 2t blocks.2 t blocchi.t blocks.

1 se t avvia orizzontale in modalità aggiornabile, entra in modalità lettura.1 If t starts out in upgradeable mode, it enters read mode. Blocca mai questa azione.This action never blocks. Lo stato del blocco rimane invariato.The lock state does not change. (Il thread possa quindi completare un downgrade alla modalità di lettura da disattivare la modalità aggiornabile.)(The thread can then complete a downgrade to read mode by exiting upgradeable mode.)

2 se t viene avviato in modalità aggiornabile, si blocca se sono presenti thread in modalità lettura.2 If t starts out in upgradeable mode, it blocks if there are threads in read mode. In caso contrario, che venga aggiornato alla modalità di scrittura.Otherwise it upgrades to write mode. I cambiamenti di stato di blocco per scrittura (S).The lock state changes to Write (W). Se t blocca perché sono presenti thread in modalità di lettura, passa alla modalità di scrittura, non appena l'ultimo thread esce dalla modalità di lettura, anche se sono presenti thread in attesa di immettere la modalità scrittura.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.

Quando una modifica dello stato è dovuto al fatto che un thread termina il blocco, il thread successivo che riattivati viene selezionato come indicato di seguito:When a state change occurs because a thread exits the lock, the next thread to be awakened is selected as follows:

  • In primo luogo, un thread in attesa per la modalità scrittura ed è già in modalità aggiornabile (possono essere presenti al massimo un thread di questo tipo).First, a thread that is waiting for write mode and is already in upgradeable mode (there can be at most one such thread).

  • In mancanza di questo, un thread in attesa per la modalità scrittura.Failing that, a thread that is waiting for write mode.

  • In mancanza di questo, un thread in attesa per la modalità aggiornabile.Failing that, a thread that is waiting for upgradeable mode.

  • Esito negativo, tutti i thread in attesa per la modalità lettura.Failing that, all threads that are waiting for read mode.

Lo stato successivo del blocco è sempre di scrittura (W) nei primi due casi e aggiornamento (U) nel terzo caso, indipendentemente dallo stato del blocco quando il thread in fase di chiusura ha attivato la modifica dello stato.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. Nell'ultimo caso, lo stato del blocco è eseguire l'aggiornamento (U) se non vi è un thread in modalità aggiornabile dopo la modifica dello stato e Read (R) in caso contrario, indipendentemente dallo stato precedente.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.

Costruttori

ReaderWriterLockSlim() ReaderWriterLockSlim() ReaderWriterLockSlim() ReaderWriterLockSlim()

Inizializza una nuova istanza della classe ReaderWriterLockSlim con i valori predefiniti delle proprietà.Initializes a new instance of the ReaderWriterLockSlim class with default property values.

ReaderWriterLockSlim(LockRecursionPolicy) ReaderWriterLockSlim(LockRecursionPolicy) ReaderWriterLockSlim(LockRecursionPolicy) ReaderWriterLockSlim(LockRecursionPolicy)

Inizializza una nuova istanza della classe ReaderWriterLockSlim, specificando i criteri di ricorsione del blocco.Initializes a new instance of the ReaderWriterLockSlim class, specifying the lock recursion policy.

Proprietà

CurrentReadCount CurrentReadCount CurrentReadCount CurrentReadCount

Ottiene il numero complessivo di thread univoci per i quali è stato attivato il blocco in modalità lettura.Gets the total number of unique threads that have entered the lock in read mode.

IsReadLockHeld IsReadLockHeld IsReadLockHeld IsReadLockHeld

Ottiene un valore che indica se per il thread corrente è stato attivato il blocco in modalità lettura.Gets a value that indicates whether the current thread has entered the lock in read mode.

IsUpgradeableReadLockHeld IsUpgradeableReadLockHeld IsUpgradeableReadLockHeld IsUpgradeableReadLockHeld

Ottiene un valore che indica se per il thread corrente è stato attivato il blocco in modalità aggiornabile.Gets a value that indicates whether the current thread has entered the lock in upgradeable mode.

IsWriteLockHeld IsWriteLockHeld IsWriteLockHeld IsWriteLockHeld

Ottiene un valore che indica se per il thread corrente è stato attivato il blocco in modalità scrittura.Gets a value that indicates whether the current thread has entered the lock in write mode.

RecursionPolicy RecursionPolicy RecursionPolicy RecursionPolicy

Ottiene un valore che indica i criteri di ricorsione per l'oggetto ReaderWriterLockSlim corrente.Gets a value that indicates the recursion policy for the current ReaderWriterLockSlim object.

RecursiveReadCount RecursiveReadCount RecursiveReadCount RecursiveReadCount

Ottiene il numero di volte in cui per il thread corrente è stato attivato il blocco in modalità lettura, come indicazione della ricorsione.Gets the number of times the current thread has entered the lock in read mode, as an indication of recursion.

RecursiveUpgradeCount RecursiveUpgradeCount RecursiveUpgradeCount RecursiveUpgradeCount

Ottiene il numero di volte in cui per il thread corrente è stato attivato il blocco in modalità aggiornabile, come indicazione della ricorsione.Gets the number of times the current thread has entered the lock in upgradeable mode, as an indication of recursion.

RecursiveWriteCount RecursiveWriteCount RecursiveWriteCount RecursiveWriteCount

Ottiene il numero di volte in cui per il thread corrente è stato attivato il blocco in modalità scrittura, come indicazione della ricorsione.Gets the number of times the current thread has entered the lock in write mode, as an indication of recursion.

WaitingReadCount WaitingReadCount WaitingReadCount WaitingReadCount

Ottiene il numero complessivo di thread in attesa di attivazione del blocco in modalità lettura.Gets the total number of threads that are waiting to enter the lock in read mode.

WaitingUpgradeCount WaitingUpgradeCount WaitingUpgradeCount WaitingUpgradeCount

Ottiene il numero complessivo di thread in attesa di attivazione del blocco in modalità aggiornabile.Gets the total number of threads that are waiting to enter the lock in upgradeable mode.

WaitingWriteCount WaitingWriteCount WaitingWriteCount WaitingWriteCount

Ottiene il numero complessivo di thread in attesa di attivazione del blocco in modalità scrittura.Gets the total number of threads that are waiting to enter the lock in write mode.

Metodi

Dispose() Dispose() Dispose() Dispose()

Rilascia tutte le risorse usate dall'istanza corrente della classe ReaderWriterLockSlim.Releases all resources used by the current instance of the ReaderWriterLockSlim class.

EnterReadLock() EnterReadLock() EnterReadLock() EnterReadLock()

Prova ad attivare il blocco in modalità lettura.Tries to enter the lock in read mode.

EnterUpgradeableReadLock() EnterUpgradeableReadLock() EnterUpgradeableReadLock() EnterUpgradeableReadLock()

Prova ad attivare il blocco in modalità aggiornabile.Tries to enter the lock in upgradeable mode.

EnterWriteLock() EnterWriteLock() EnterWriteLock() EnterWriteLock()

Prova ad attivare il blocco in modalità scrittura.Tries to enter the lock in write mode.

Equals(Object) Equals(Object) Equals(Object) Equals(Object)

Determina se l'oggetto specificato è uguale all'oggetto corrente.Determines whether the specified object is equal to the current object.

(Inherited from Object)
ExitReadLock() ExitReadLock() ExitReadLock() ExitReadLock()

Riduce il numero di ricorsioni per la modalità lettura ed esce da questa modalità se il numero risultante è 0 (zero).Reduces the recursion count for read mode, and exits read mode if the resulting count is 0 (zero).

ExitUpgradeableReadLock() ExitUpgradeableReadLock() ExitUpgradeableReadLock() ExitUpgradeableReadLock()

Riduce il numero di ricorsioni per la modalità aggiornabile ed esce da questa modalità se il numero risultante è 0 (zero).Reduces the recursion count for upgradeable mode, and exits upgradeable mode if the resulting count is 0 (zero).

ExitWriteLock() ExitWriteLock() ExitWriteLock() ExitWriteLock()

Riduce il numero di ricorsioni per la modalità scrittura ed esce da questa modalità se il numero risultante è 0 (zero).Reduces the recursion count for write mode, and exits write mode if the resulting count is 0 (zero).

GetHashCode() GetHashCode() GetHashCode() GetHashCode()

Funge da funzione hash predefinita.Serves as the default hash function.

(Inherited from Object)
GetType() GetType() GetType() GetType()

Ottiene l'oggetto Type dell'istanza corrente.Gets the Type of the current instance.

(Inherited from Object)
MemberwiseClone() MemberwiseClone() MemberwiseClone() MemberwiseClone()

Crea una copia superficiale dell'oggetto Object corrente.Creates a shallow copy of the current Object.

(Inherited from Object)
ToString() ToString() ToString() ToString()

Restituisce una stringa che rappresenta l'oggetto corrente.Returns a string that represents the current object.

(Inherited from Object)
TryEnterReadLock(Int32) TryEnterReadLock(Int32) TryEnterReadLock(Int32) TryEnterReadLock(Int32)

Prova ad attivare il blocco in modalità lettura con un timeout intero facoltativo.Tries to enter the lock in read mode, with an optional integer time-out.

TryEnterReadLock(TimeSpan) TryEnterReadLock(TimeSpan) TryEnterReadLock(TimeSpan) TryEnterReadLock(TimeSpan)

Prova ad attivare il blocco in modalità lettura con un timeout facoltativo.Tries to enter the lock in read mode, with an optional time-out.

TryEnterUpgradeableReadLock(Int32) TryEnterUpgradeableReadLock(Int32) TryEnterUpgradeableReadLock(Int32) TryEnterUpgradeableReadLock(Int32)

Prova ad attivare il blocco in modalità aggiornabile con un timeout facoltativo.Tries to enter the lock in upgradeable mode, with an optional time-out.

TryEnterUpgradeableReadLock(TimeSpan) TryEnterUpgradeableReadLock(TimeSpan) TryEnterUpgradeableReadLock(TimeSpan) TryEnterUpgradeableReadLock(TimeSpan)

Prova ad attivare il blocco in modalità aggiornabile con un timeout facoltativo.Tries to enter the lock in upgradeable mode, with an optional time-out.

TryEnterWriteLock(Int32) TryEnterWriteLock(Int32) TryEnterWriteLock(Int32) TryEnterWriteLock(Int32)

Prova ad attivare il blocco in modalità scrittura con un timeout facoltativo.Tries to enter the lock in write mode, with an optional time-out.

TryEnterWriteLock(TimeSpan) TryEnterWriteLock(TimeSpan) TryEnterWriteLock(TimeSpan) TryEnterWriteLock(TimeSpan)

Prova ad attivare il blocco in modalità scrittura con un timeout facoltativo.Tries to enter the lock in write mode, with an optional time-out.

Si applica a

Thread safety

Questo tipo è thread-safe.This type is thread safe.