ReaderWriterLockSlim ReaderWriterLockSlim ReaderWriterLockSlim ReaderWriterLockSlim Class

Definición

Representa un bloqueo que se utiliza para administrar el acceso a un recurso y que permite varios subprocesos para la lectura o acceso exclusivo para la escritura.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
Herencia
ReaderWriterLockSlimReaderWriterLockSlimReaderWriterLockSlimReaderWriterLockSlim
Implementaciones

Ejemplos

En el ejemplo siguiente se muestra una memoria caché sincronizada simple que contiene cadenas con claves enteras.The following example shows a simple synchronized cache that holds strings with integer keys. Una instancia de ReaderWriterLockSlim se utiliza para sincronizar el Dictionary<TKey,TValue> acceso a que actúa como la memoria caché interna.An instance of ReaderWriterLockSlim is used to synchronize access to the Dictionary<TKey,TValue> that serves as the inner cache.

El ejemplo incluye métodos simples para agregar a la memoria caché, eliminar de la memoria caché y leer de la memoria caché.The example includes simple methods to add to the cache, delete from the cache, and read from the cache. Para mostrar los tiempos de espera, el ejemplo incluye un método que agrega a la memoria caché solo si puede hacerlo dentro de un tiempo de espera especificado.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.

Para demostrar el modo de actualización, el ejemplo incluye un método que recupera el valor asociado a una clave y lo compara con un nuevo valor.To demonstrate upgradeable mode, the example includes a method that retrieves the value associated with a key and compares it with a new value. Si el valor no ha cambiado, el método devuelve un estado que indica que no hay cambios.If the value is unchanged, the method returns a status indicating no change. Si no se encuentra ningún valor para la clave, se inserta el par clave-valor.If no value is found for the key, the key/value pair is inserted. Si el valor ha cambiado, se actualiza.If the value has changed, it is updated. El modo de actualización permite al subproceso actualizar el acceso de lectura al acceso de escritura según sea necesario, sin el riesgo de interbloqueos.Upgradeable mode allows the thread to upgrade from read access to write access as needed, without the risk of deadlocks.

En el ejemplo se incluye una enumeración anidada que especifica los valores devueltos para el método que muestra el modo de actualización.The example includes a nested enumeration that specifies the return values for the method that demonstrates upgradeable mode.

En el ejemplo se utiliza el constructor sin parámetros para crear el bloqueo, por lo que no se permite la recursividad.The example uses the parameterless constructor to create the lock, so recursion is not allowed. La programación ReaderWriterLockSlim de es más sencilla y menos propensa a errores cuando el bloqueo no permite la recursividad.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

A continuación, el siguiente código SynchronizedCache usa el objeto para almacenar un diccionario de nombres de verduras.The following code then uses the SynchronizedCache object to store a dictionary of vegetable names. Crea tres tareas.It creates three tasks. El primero escribe los nombres de las verduras almacenadas en una matriz SynchronizedCache en una instancia.The first writes the names of vegetables stored in an array to a SynchronizedCache instance. La segunda y tercera tarea muestran los nombres de las verduras, el primero en orden ascendente (de índice inferior a índice alto), el segundo en orden descendente.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. La tarea final busca la cadena "Cucumber" y, cuando la encuentra, llama EnterUpgradeableReadLock al método para sustituir la cadena "Green 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

Comentarios

Use ReaderWriterLockSlim para proteger un recurso leído por varios subprocesos y escrito en un subproceso cada vez.Use ReaderWriterLockSlim to protect a resource that is read by multiple threads and written to by one thread at a time. ReaderWriterLockSlimpermite que varios subprocesos estén en modo de lectura, permite que un subproceso esté en modo de escritura con propiedad exclusiva del bloqueo y permite que un subproceso que tenga acceso de lectura esté en modo de lectura actualizable, desde el que el subproceso puede actualizarse al modo de escritura sin tener que renunciar s acceso de lectura al recurso.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 es similar a ReaderWriterLock, pero se han simplificado las reglas para la recursividad y para actualizar y degradar el estado de bloqueo.ReaderWriterLockSlim is similar to ReaderWriterLock, but it has simplified rules for recursion and for upgrading and downgrading lock state. ReaderWriterLockSlim evita muchos casos de interbloqueo potencial.ReaderWriterLockSlim avoids many cases of potential deadlock. Además, el rendimiento de ReaderWriterLockSlim es significativamente mayor que ReaderWriterLock.In addition, the performance of ReaderWriterLockSlim is significantly better than ReaderWriterLock. ReaderWriterLockSlim se recomienda para todos los nuevos desarrollos.ReaderWriterLockSlim is recommended for all new development.

De forma predeterminada, se crean ReaderWriterLockSlim nuevas instancias de con LockRecursionPolicy.NoRecursion la marca y no se permite la recursividad.By default, new instances of ReaderWriterLockSlim are created with the LockRecursionPolicy.NoRecursion flag and do not allow recursion. Esta directiva predeterminada se recomienda para todo el desarrollo nuevo, ya que la recursividad introduce complicaciones innecesarias y hace que el código sea más propenso a interbloqueos.This default policy is recommended for all new development, because recursion introduces unnecessary complications and makes your code more prone to deadlocks. Para simplificar la migración de proyectos existentes Monitor que ReaderWriterLockusan o, puede usar LockRecursionPolicy.SupportsRecursion la marca para crear instancias ReaderWriterLockSlim de que permitan la recursividad.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 subproceso puede entrar en el bloqueo en tres modos: modo de lectura, modo de escritura y modo de lectura actualizable.A thread can enter the lock in three modes: read mode, write mode, and upgradeable read mode. (En el resto de este tema, "modo de lectura actualizable" se conoce como "modo de actualización" y la frase "entrar x en modo" se usa en preferencia a la frase más larga "entrar en el bloqueo en x modo".)(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".)

Independientemente de la Directiva de recursividad, solo un subproceso puede estar en modo de escritura en cualquier momento.Regardless of recursion policy, only one thread can be in write mode at any time. Cuando un subproceso está en modo de escritura, ningún otro subproceso puede entrar en el bloqueo en ningún modo.When a thread is in write mode, no other thread can enter the lock in any mode. Solo un subproceso puede estar en modo de actualización en cualquier momento.Only one thread can be in upgradeable mode at any time. Cualquier número de subprocesos puede estar en modo de lectura y puede haber un subproceso en modo de actualización mientras otros subprocesos están en modo de lectura.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

Este tipo implementa la interfaz IDisposable.This type implements the IDisposable interface. Cuando haya terminado de utilizar el tipo, debe desecharlo directa o indirectamente.When you have finished using the type, you should dispose of it either directly or indirectly. Para eliminar el tipo directamente, llame a su método Dispose en un bloque try/catch.To dispose of the type directly, call its Dispose method in a try/catch block. Para deshacerse de él indirectamente, use una construcción de lenguaje como using (en C#) o Using (en Visual Basic).To dispose of it indirectly, use a language construct such as using (in C#) or Using (in Visual Basic). Para más información, vea la sección "Uso de objetos que implementan IDisposable" en el tema de la interfaz IDisposable.For more information, see the "Using an Object that Implements IDisposable" section in the IDisposable interface topic.

ReaderWriterLockSlimtiene afinidad de subprocesos administrados; es decir, cada Thread objeto debe realizar sus propias llamadas al método para entrar y salir de los modos de bloqueo.ReaderWriterLockSlim has managed thread affinity; that is, each Thread object must make its own method calls to enter and exit lock modes. Ningún subproceso puede cambiar el modo de otro subproceso.No thread can change the mode of another thread.

ReaderWriterLockSlim Si no permite la recursividad, un subproceso que intenta entrar en el bloqueo puede bloquearse por varios motivos:If a ReaderWriterLockSlim does not allow recursion, a thread that tries to enter the lock can block for several reasons:

  • Un subproceso que intenta entrar en los bloques de modo de lectura si hay subprocesos a la espera de entrar en modo de escritura o si hay un único subproceso en modo de escritura.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

    Bloquear nuevos lectores cuando se ponen en cola los escritores es una directiva de equidad de bloqueo que favorece a los escritores.Blocking new readers when writers are queued is a lock fairness policy that favors writers. La Directiva de equidad actual equilibra la equidad con los lectores y escritores para promover el rendimiento en los escenarios más comunes.The current fairness policy balances fairness to readers and writers, to promote throughput in the most common scenarios. Las versiones futuras de .NET Framework.NET Framework pueden introducir nuevas directivas de equidad.Future versions of the .NET Framework.NET Framework may introduce new fairness policies.

  • Subproceso que intenta entrar en los bloques de modo de actualización si ya existe un subproceso en modo de actualización, si hay subprocesos a la espera de entrar en el modo de escritura o si hay un único subproceso en modo de escritura.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 subproceso que intenta entrar en los bloques de modo de escritura si hay un subproceso en cualquiera de los tres modos.A thread that tries to enter write mode blocks if there is a thread in any of the three modes.

Actualización y degradación de los bloqueosUpgrading and Downgrading Locks

El modo de actualización está pensado para los casos en los que un subproceso normalmente Lee del recurso protegido, pero puede que tenga que escribir en él si se cumple alguna condición.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 subproceso que ha entrado ReaderWriterLockSlim en modo de actualización tiene acceso de lectura al recurso protegido y puede actualizarse al modo de escritura mediante una llamada EnterWriteLock a TryEnterWriteLock los métodos o.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. Dado que solo puede haber un subproceso en modo de actualización a la vez, al actualizar el modo de escritura no se puede crear un interbloqueo cuando no se permite la recursividad, que es la directiva predeterminada.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

Independientemente de la Directiva de recursividad, no se permite que un subproceso que entró inicialmente en modo de lectura se actualice al modo de escritura o al modo de actualización, ya que ese patrón crea una probabilidad fuerte de interbloqueos.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. Por ejemplo, si dos subprocesos en modo de lectura intentan entrar en modo de escritura, se interbloquearán.For example, if two threads in read mode both try to enter write mode, they will deadlock. El modo de actualización está diseñado para evitar estos interbloqueos.Upgradeable mode is designed to avoid such deadlocks.

Si hay otros subprocesos en modo de lectura, el subproceso que está actualizando los bloques.If there are other threads in read mode, the thread that is upgrading blocks. Mientras se bloquea el subproceso, se bloquean otros subprocesos que intentan entrar en modo de lectura.While the thread is blocked, other threads that try to enter read mode are blocked. Cuando todos los subprocesos salen del modo de lectura, el subproceso de actualización bloqueado entra en el modo de escritura.When all threads have exited from read mode, the blocked upgradeable thread enters write mode. Si hay otros subprocesos a la espera de entrar en modo de escritura, permanecen bloqueados, ya que el único subproceso que está en modo de actualización impide que obtenga acceso exclusivo al recurso.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.

Cuando el subproceso en modo de actualización sale del modo de escritura, pueden hacerlo otros subprocesos que están a la espera de entrar en modo de lectura, a menos que haya subprocesos a la espera de entrar en modo de escritura.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. El subproceso en modo de actualización puede actualizarse y degradarse indefinidamente, siempre y cuando sea el único subproceso que escribe en el recurso protegido.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

Si permite que varios subprocesos entren en el modo de escritura o en el modo de actualización, no debe permitir que un subproceso monopolice el modo de actualización.If you allow multiple threads to enter write mode or upgradeable mode, you must not allow one thread to monopolize upgradeable mode. De lo contrario, los subprocesos que intenten entrar en modo de escritura directamente se bloquearán de forma indefinida y mientras estén bloqueados, otros subprocesos no podrán entrar en modo de lectura.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.

Un subproceso en modo de actualización puede cambiar al modo de lectura llamando primero al EnterReadLock método y, a continuación, llamando al ExitUpgradeableReadLock método.A thread in upgradeable mode can downgrade to read mode by first calling the EnterReadLock method and then calling the ExitUpgradeableReadLock method. Este patrón de degradación se permite para todas las directivas de recursividad NoRecursionde bloqueo, incluso.This downgrade pattern is allowed for all lock recursion policies, even NoRecursion.

Después de degradar al modo de lectura, un subproceso no puede volver a entrar en modo de actualización hasta que sale del modo de lectura.After downgrading to read mode, a thread cannot reenter upgradeable mode until it has exited from read mode.

Escribir el bloqueo de forma recursivaEntering the Lock Recursively

Puede crear un ReaderWriterLockSlim que admita la entrada de bloqueo recursivo mediante el constructor ReaderWriterLockSlim(LockRecursionPolicy) que especifica la LockRecursionPolicy.SupportsRecursionDirectiva de bloqueo y la especificación de.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

No se recomienda el uso de la recursividad para el nuevo desarrollo, ya que presenta complicaciones innecesarias y hace que el código sea más propenso a interbloqueos.The use of recursion is not recommended for new development, because it introduces unnecessary complications and makes your code more prone to deadlocks.

En el caso de quepermitalarecursividad,sepuededecirlosiguientesobrelosmodosqueunsubprocesopuedeescribir:ReaderWriterLockSlimFor a ReaderWriterLockSlim that allows recursion, the following can be said about the modes a thread can enter:

  • Un subproceso en modo de lectura puede entrar en modo de lectura de forma recursiva, pero no puede entrar en modo de escritura o en modo de actualización.A thread in read mode can enter read mode recursively, but cannot enter write mode or upgradeable mode. Si intenta hacer esto, se produce una LockRecursionException excepción.If it tries to do this, a LockRecursionException is thrown. Entrar en modo de lectura y, a continuación, especificar el modo de escritura o el modo de actualización es un patrón con una probabilidad fuerte de interbloqueos, por lo que no se permite.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. Como se explicó anteriormente, se proporciona el modo de actualización para los casos en los que es necesario actualizar un bloqueo.As discussed earlier, upgradeable mode is provided for cases where it is necessary to upgrade a lock.

  • Un subproceso en modo de actualización puede entrar en modo de escritura o en modo de lectura, y puede entrar en cualquiera de los tres modos de forma recursiva.A thread in upgradeable mode can enter write mode and/or read mode, and can enter any of the three modes recursively. Sin embargo, un intento de entrar en modo de escritura se bloquea si hay otros subprocesos en modo de lectura.However, an attempt to enter write mode blocks if there are other threads in read mode.

  • Un subproceso en modo de escritura puede entrar en modo de lectura o en modo de actualización y puede entrar en cualquiera de los tres modos de forma recursiva.A thread in write mode can enter read mode and/or upgradeable mode, and can enter any of the three modes recursively.

  • Un subproceso que no ha entrado en el bloqueo puede entrar en cualquier modo.A thread that has not entered the lock can enter any mode. Este intento puede bloquearse por las mismas razones que un intento de entrar en un bloqueo No recursivo.This attempt can block for the same reasons as an attempt to enter a non-recursive lock.

Un subproceso puede salir de los modos que ha escrito en cualquier orden, siempre que salga de cada modo exactamente tantas veces como se entró en ese modo.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. Si un subproceso intenta salir de un modo demasiadas veces, o para salir de un modo que no ha escrito SynchronizationLockException , se produce una excepción.If a thread tries to exit a mode too many times, or to exit a mode it has not entered, a SynchronizationLockException is thrown.

Estados de bloqueoLock States

Puede que le resulte útil pensar en el bloqueo en cuanto a sus Estados.You may find it useful to think of the lock in terms of its states. ReaderWriterLockSlim Puede estar en uno de cuatro Estados: no especificado, lectura, actualización y escritura.A ReaderWriterLockSlim can be in one of four states: not entered, read, upgrade, and write.

  • No especificado: En este estado, ningún subproceso ha entrado en el bloqueo (o todos los subprocesos han salido del bloqueo).Not entered: In this state, no threads have entered the lock (or all threads have exited the lock).

  • Lectura En este estado, uno o más subprocesos han entrado en el bloqueo para el acceso de lectura al recurso protegido.Read: In this state, one or more threads have entered the lock for read access to the protected resource.

    Nota

    Un subproceso puede entrar en el bloqueo en modo de lectura EnterReadLock mediante TryEnterReadLock los métodos o, o bien degradando el modo de actualización.A thread can enter the lock in read mode by using the EnterReadLock or TryEnterReadLock methods, or by downgrading from upgradeable mode.

  • Actualización En este estado, un subproceso ha entrado en el bloqueo para el acceso de lectura con la opción de actualizar el acceso de escritura (es decir, en modo de actualización) y cero o más subprocesos han entrado en el bloqueo para el acceso de lectura.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. No más de un subproceso a la vez puede entrar en el bloqueo con la opción de actualización; se bloquean los subprocesos adicionales que intentan entrar en modo de actualización.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.

  • Escribi En este estado, un subproceso ha entrado en el bloqueo para el acceso de escritura al recurso protegido.Write: In this state, one thread has entered the lock for write access to the protected resource. Ese subproceso tiene posesión exclusiva del bloqueo.That thread has exclusive possession of the lock. Cualquier otro subproceso que intente entrar en el bloqueo por cualquier motivo está bloqueado.Any other thread that tries to enter the lock for any reason is blocked.

En la tabla siguiente se describen las transiciones entre los Estados de bloqueo, los bloqueos que no permiten la t recursividad, cuando un subproceso realiza la acción descrita en la columna situada más a la izquierda.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. En el momento en que se lleva a t cabo la acción, no tiene ningún modo.At the time it takes the action, t has no mode. (El caso especial en t el que se encuentra en modo de actualización se describe en las notas al pie de tabla). La fila superior describe el estado inicial del bloqueo.(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. Las celdas describen lo que sucede en el subproceso y muestran los cambios en el estado de bloqueo entre paréntesis.The cells describe what happens to the thread, and show changes to the lock state in parentheses.

No especificado (N)Not entered (N) Lectura (R)Read (R) Actualizar (U)Upgrade (U) Escritura (W)Write (W)
tentra en modo de lecturat enters read mode tescribe (R).t enters (R). tbloquea si los subprocesos están esperando el modo de escritura; de lo t contrario, escribe.t blocks if threads are waiting for write mode; otherwise, t enters. tbloquea si los subprocesos están esperando el modo de escritura; de lo t contrario, escribe. 1t blocks if threads are waiting for write mode; otherwise, t enters.1 tcatch.t blocks.
tentra en modo de actualizaciónt enters upgradeable mode tescribe (U).t enters (U). tbloquea si los subprocesos están esperando el modo de escritura o el modo de actualización; de lo t contrario, escribe (U).t blocks if threads are waiting for write mode or upgrade mode; otherwise, t enters (U). tcatch.t blocks. tcatch.t blocks.
tentra en el modo de escriturat enters write mode tescribe (W).t enters (W). tcatch.t blocks. tcatch. 2t blocks.2 tcatch.t blocks.

1 si t se inicia en modo de actualización, entra en modo de lectura.1 If t starts out in upgradeable mode, it enters read mode. Esta acción nunca se bloquea.This action never blocks. El estado de bloqueo no cambia.The lock state does not change. (El subproceso puede completar una degradación al modo de lectura saliendo del modo de actualización).(The thread can then complete a downgrade to read mode by exiting upgradeable mode.)

2 si t se inicia en modo de actualización, se bloquea si hay subprocesos en modo de lectura.2 If t starts out in upgradeable mode, it blocks if there are threads in read mode. De lo contrario, actualiza al modo de escritura.Otherwise it upgrades to write mode. El estado de bloqueo cambia a escritura (W).The lock state changes to Write (W). Si t se bloquea porque hay subprocesos en modo de lectura, entra en el modo de escritura en cuanto el último subproceso sale del modo de lectura, incluso si hay subprocesos a la espera de entrar en modo de escritura.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.

Cuando se produce un cambio de estado porque un subproceso sale del bloqueo, se selecciona el siguiente subproceso que se va a activar de la siguiente manera:When a state change occurs because a thread exits the lock, the next thread to be awakened is selected as follows:

  • En primer lugar, un subproceso que está esperando el modo de escritura y ya está en modo de actualización (puede haber como máximo un subproceso de este tipo).First, a thread that is waiting for write mode and is already in upgradeable mode (there can be at most one such thread).

  • Con errores, un subproceso que está esperando el modo de escritura.Failing that, a thread that is waiting for write mode.

  • Con errores, un subproceso que está esperando el modo de actualización.Failing that, a thread that is waiting for upgradeable mode.

  • Con errores, todos los subprocesos que están esperando el modo de lectura.Failing that, all threads that are waiting for read mode.

El estado subsiguiente del bloqueo siempre es escribir (W) en los dos primeros casos y actualizar (U) en el tercer caso, independientemente del estado del bloqueo cuando el subproceso que sale desencadena el cambio de estado.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. En el último caso, el estado del bloqueo es upgrade (U) si hay un subproceso en modo de actualización después del cambio de estado y Read (R) en caso contrario, independientemente del estado anterior.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.

Constructores

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

Inicializa una nueva instancia de la clase ReaderWriterLockSlim con los valores de propiedad predeterminados.Initializes a new instance of the ReaderWriterLockSlim class with default property values.

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

Inicializa una nueva instancia de la clase ReaderWriterLockSlim especificando la directiva de recursividad de bloqueo.Initializes a new instance of the ReaderWriterLockSlim class, specifying the lock recursion policy.

Propiedades

CurrentReadCount CurrentReadCount CurrentReadCount CurrentReadCount

Obtiene el número total de subprocesos únicos que han entrado en el bloqueo en modo de lectura.Gets the total number of unique threads that have entered the lock in read mode.

IsReadLockHeld IsReadLockHeld IsReadLockHeld IsReadLockHeld

Obtiene un valor que indica si el subproceso actual ha entrado en el bloqueo en modo de lectura.Gets a value that indicates whether the current thread has entered the lock in read mode.

IsUpgradeableReadLockHeld IsUpgradeableReadLockHeld IsUpgradeableReadLockHeld IsUpgradeableReadLockHeld

Obtiene un valor que indica si el subproceso actual ha entrado en el bloqueo en modo de actualización.Gets a value that indicates whether the current thread has entered the lock in upgradeable mode.

IsWriteLockHeld IsWriteLockHeld IsWriteLockHeld IsWriteLockHeld

Obtiene un valor que indica si el subproceso actual ha entrado en el bloqueo en modo de escritura.Gets a value that indicates whether the current thread has entered the lock in write mode.

RecursionPolicy RecursionPolicy RecursionPolicy RecursionPolicy

Obtiene un valor que indica la directiva de recursividad del objeto ReaderWriterLockSlim actual.Gets a value that indicates the recursion policy for the current ReaderWriterLockSlim object.

RecursiveReadCount RecursiveReadCount RecursiveReadCount RecursiveReadCount

Obtiene el número de veces que el subproceso actual ha entrado en el bloqueo en modo de lectura, como una indicación de recursividad.Gets the number of times the current thread has entered the lock in read mode, as an indication of recursion.

RecursiveUpgradeCount RecursiveUpgradeCount RecursiveUpgradeCount RecursiveUpgradeCount

Obtiene el número de veces que el subproceso actual ha entrado en el bloqueo en modo de actualización, como una indicación de recursividad.Gets the number of times the current thread has entered the lock in upgradeable mode, as an indication of recursion.

RecursiveWriteCount RecursiveWriteCount RecursiveWriteCount RecursiveWriteCount

Obtiene el número de veces que el subproceso actual ha entrado en el bloqueo en modo de escritura, como una indicación de recursividad.Gets the number of times the current thread has entered the lock in write mode, as an indication of recursion.

WaitingReadCount WaitingReadCount WaitingReadCount WaitingReadCount

Obtiene el número total de subprocesos que están a la espera de entrar en el bloqueo en modo de lectura.Gets the total number of threads that are waiting to enter the lock in read mode.

WaitingUpgradeCount WaitingUpgradeCount WaitingUpgradeCount WaitingUpgradeCount

Obtiene el número total de subprocesos que están a la espera de entrar en el bloqueo en modo de actualización.Gets the total number of threads that are waiting to enter the lock in upgradeable mode.

WaitingWriteCount WaitingWriteCount WaitingWriteCount WaitingWriteCount

Obtiene el número total de subprocesos que están a la espera de entrar en el bloqueo en modo de escritura.Gets the total number of threads that are waiting to enter the lock in write mode.

Métodos

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

Libera todos los recursos usados por la instancia actual de la clase ReaderWriterLockSlim.Releases all resources used by the current instance of the ReaderWriterLockSlim class.

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

Intenta entrar en el bloqueo en modo de lectura.Tries to enter the lock in read mode.

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

Intenta entrar en el bloqueo en modo de actualización.Tries to enter the lock in upgradeable mode.

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

Intenta entrar en el bloqueo en modo de escritura.Tries to enter the lock in write mode.

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

Determina si el objeto especificado es igual al objeto actual.Determines whether the specified object is equal to the current object.

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

Reduce el recuento de recursividad para el modo de lectura y sale del modo de lectura si el recuento resultante es 0 (cero).Reduces the recursion count for read mode, and exits read mode if the resulting count is 0 (zero).

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

Reduce el recuento de recursividad para el modo de actualización y sale del modo de actualización si el recuento resultante es 0 (cero).Reduces the recursion count for upgradeable mode, and exits upgradeable mode if the resulting count is 0 (zero).

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

Reduce el recuento de recursividad para el modo de escritura y sale del modo de escritura si el recuento resultante es 0 (cero).Reduces the recursion count for write mode, and exits write mode if the resulting count is 0 (zero).

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

Sirve como la función hash predeterminada.Serves as the default hash function.

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

Obtiene el Type de la instancia actual.Gets the Type of the current instance.

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

Crea una copia superficial del objeto Object actual.Creates a shallow copy of the current Object.

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

Devuelve una cadena que representa el objeto actual.Returns a string that represents the current object.

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

Intenta entrar en el bloqueo en modo de lectura, con un tiempo de espera entero opcional.Tries to enter the lock in read mode, with an optional integer time-out.

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

Intenta entrar en el bloqueo en modo de lectura, con tiempo de espera opcional.Tries to enter the lock in read mode, with an optional time-out.

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

Intenta entrar en el bloqueo en modo de actualización, con tiempo de espera opcional.Tries to enter the lock in upgradeable mode, with an optional time-out.

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

Intenta entrar en el bloqueo en modo de actualización, con tiempo de espera opcional.Tries to enter the lock in upgradeable mode, with an optional time-out.

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

Intenta entrar en el bloqueo en modo de escritura, con tiempo de espera opcional.Tries to enter the lock in write mode, with an optional time-out.

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

Intenta entrar en el bloqueo en modo de escritura, con tiempo de espera opcional.Tries to enter the lock in write mode, with an optional time-out.

Se aplica a

Seguridad para subprocesos

Este tipo es seguro para la ejecución de subprocesos.This type is thread safe.