ReaderWriterLockSlim ReaderWriterLockSlim ReaderWriterLockSlim ReaderWriterLockSlim Class

Définition

Représente un verrou utilisé pour gérer l'accès à une ressource, en autorisant plusieurs threads pour la lecture ou un accès exclusif en écriture.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
Héritage
ReaderWriterLockSlimReaderWriterLockSlimReaderWriterLockSlimReaderWriterLockSlim
Implémente

Exemples

L’exemple suivant montre un cache synchronisé simple qui contient des chaînes avec des clés entières.The following example shows a simple synchronized cache that holds strings with integer keys. Une instance de ReaderWriterLockSlim est utilisée pour synchroniser l’accès Dictionary<TKey,TValue> à qui sert de cache interne.An instance of ReaderWriterLockSlim is used to synchronize access to the Dictionary<TKey,TValue> that serves as the inner cache.

L’exemple comprend des méthodes simples à ajouter au cache, une suppression dans le cache et une lecture à partir du cache.The example includes simple methods to add to the cache, delete from the cache, and read from the cache. Pour illustrer les délais d’attente, l’exemple inclut une méthode qui ajoute au cache uniquement si elle peut le faire dans un délai d’attente spécifié.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.

Pour illustrer le mode de mise à niveau, l’exemple comprend une méthode qui récupère la valeur associée à une clé et la compare à une nouvelle valeur.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 la valeur est inchangée, la méthode retourne un état indiquant qu’aucune modification n’est apportée.If the value is unchanged, the method returns a status indicating no change. Si aucune valeur n’est trouvée pour la clé, la paire clé/valeur est insérée.If no value is found for the key, the key/value pair is inserted. Si la valeur a changé, elle est mise à jour.If the value has changed, it is updated. Le mode de mise à niveau permet au thread de mettre à niveau l’accès en lecture à l’accès en écriture, si nécessaire, sans risque d’interblocage.Upgradeable mode allows the thread to upgrade from read access to write access as needed, without the risk of deadlocks.

L’exemple comprend une énumération imbriquée qui spécifie les valeurs de retour de la méthode qui illustre le mode de mise à niveau.The example includes a nested enumeration that specifies the return values for the method that demonstrates upgradeable mode.

L’exemple utilise le constructeur sans paramètre pour créer le verrou, donc la récursivité n’est pas autorisée.The example uses the parameterless constructor to create the lock, so recursion is not allowed. La programmation ReaderWriterLockSlim du est plus simple et moins sujette à une erreur lorsque le verrou n’autorise pas la récursivité.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

Le code suivant utilise ensuite l' SynchronizedCache objet pour stocker un dictionnaire de noms de légumes.The following code then uses the SynchronizedCache object to store a dictionary of vegetable names. Il crée trois tâches.It creates three tasks. La première écrit les noms des légumes stockés dans un tableau dans une SynchronizedCache instance.The first writes the names of vegetables stored in an array to a SynchronizedCache instance. La deuxième et la troisième tâche affichent les noms des légumes, le premier dans l’ordre croissant (de l’index faible à l’index le plus élevé), le second dans l’ordre décroissant.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 dernière tâche recherche la chaîne «concombre» et, lorsqu’elle la trouve, appelle la EnterUpgradeableReadLock méthode pour remplacer la chaîne «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

Remarques

Utilisez ReaderWriterLockSlim pour protéger une ressource lue par plusieurs threads et écrite par un thread à la fois.Use ReaderWriterLockSlim to protect a resource that is read by multiple threads and written to by one thread at a time. ReaderWriterLockSlimpermet à plusieurs threads d’être en mode lecture, permet à un thread d’être en mode écriture avec la propriété exclusive du verrou et autorise un thread ayant un accès en lecture à être en mode de lecture à la mise à niveau, à partir duquel le thread peut effectuer une mise à niveau vers le mode écriture sans avoir à le abandonner accès en lecture à la ressource.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.

Notes

ReaderWriterLockSlim est similaire à ReaderWriterLock, mais a des règles simplifiées pour la récursivité ainsi que la mise à niveau et la rétrogradation de l’état de verrou.ReaderWriterLockSlim is similar to ReaderWriterLock, but it has simplified rules for recursion and for upgrading and downgrading lock state. ReaderWriterLockSlim évite de nombreux cas d’interblocage potentiel.ReaderWriterLockSlim avoids many cases of potential deadlock. En outre, les performances de ReaderWriterLockSlim sont considérablement meilleures que celles de ReaderWriterLock.In addition, the performance of ReaderWriterLockSlim is significantly better than ReaderWriterLock. ReaderWriterLockSlim est recommandé pour tout nouveau développement.ReaderWriterLockSlim is recommended for all new development.

Par défaut, les nouvelles instances ReaderWriterLockSlim de sont créées avec LockRecursionPolicy.NoRecursion l’indicateur et n’autorisent pas la récursivité.By default, new instances of ReaderWriterLockSlim are created with the LockRecursionPolicy.NoRecursion flag and do not allow recursion. Cette stratégie par défaut est recommandée pour tout nouveau développement, car la récursivité introduit des complications inutiles et rend votre code plus sujet aux blocages.This default policy is recommended for all new development, because recursion introduces unnecessary complications and makes your code more prone to deadlocks. Pour simplifier la migration à partir de projets Monitor existants ReaderWriterLockqui utilisent ou, vous LockRecursionPolicy.SupportsRecursion pouvez utiliser l’indicateur pour ReaderWriterLockSlim créer des instances de qui autorisent la récursivité.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 peut entrer le verrou en trois modes: le mode lecture, le mode écriture et le mode de lecture avec mise à niveau.A thread can enter the lock in three modes: read mode, write mode, and upgradeable read mode. (Dans le reste de cette rubrique, «mode de lecture avec mise à niveau» est appelé «mode de mise à niveau», x et l’expression «mode entrée» est utilisée par préférence à la phrase plus x longue «entrer le verrou en mode».)(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".)

Quelle que soit la stratégie de récurrence, un seul thread peut être en mode écriture à tout moment.Regardless of recursion policy, only one thread can be in write mode at any time. Quand un thread est en mode écriture, aucun autre thread ne peut entrer le verrou dans aucun mode.When a thread is in write mode, no other thread can enter the lock in any mode. Un seul thread peut être en mode de mise à niveau à tout moment.Only one thread can be in upgradeable mode at any time. Un nombre quelconque de threads peut être en mode lecture, et il peut y avoir un thread en mode de mise à niveau, tandis que d’autres threads sont en mode lecture.Any number of threads can be in read mode, and there can be one thread in upgradeable mode while other threads are in read mode.

Important

Ce type implémente l'interface IDisposable.This type implements the IDisposable interface. Une fois que vous avez fini d’utiliser le type, vous devez le supprimer directement ou indirectement.When you have finished using the type, you should dispose of it either directly or indirectly. Pour supprimer directement le type Dispose, appelez sa méthode dans un bloc try/catch.To dispose of the type directly, call its Dispose method in a try/catch block. Pour la supprimer indirectement, utilisez une construction de langage telle que using (dans C#) ou Using (dans Visual Basic).To dispose of it indirectly, use a language construct such as using (in C#) or Using (in Visual Basic). Pour plus d’informations, consultez la section « Utilisation d’un objet qui implémente IDisposable » dans la rubrique de l’interface IDisposable.For more information, see the "Using an Object that Implements IDisposable" section in the IDisposable interface topic.

ReaderWriterLockSlima une affinité de thread managée; autrement dit, chaque Thread objet doit effectuer ses propres appels de méthode aux modes de verrouillage Enter et Exit.ReaderWriterLockSlim has managed thread affinity; that is, each Thread object must make its own method calls to enter and exit lock modes. Aucun thread ne peut modifier le mode d’un autre thread.No thread can change the mode of another thread.

Si un ReaderWriterLockSlim n’autorise pas la récursivité, un thread qui tente d’entrer le verrou peut bloquer pour plusieurs raisons:If a ReaderWriterLockSlim does not allow recursion, a thread that tries to enter the lock can block for several reasons:

  • Thread qui tente d’entrer des blocs en mode lecture si des threads attendent pour entrer en mode écriture ou s’il existe un seul thread en mode écriture.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.

    Notes

    Le blocage de nouveaux lecteurs lorsque des enregistreurs sont mis en file d’attente est une stratégie d’équité de verrou qui favorise les writers.Blocking new readers when writers are queued is a lock fairness policy that favors writers. La stratégie d’équité actuelle équilibre l’équité entre les lecteurs et les enregistreurs, afin de promouvoir le débit dans les scénarios les plus courants.The current fairness policy balances fairness to readers and writers, to promote throughput in the most common scenarios. Les .NET Framework.NET Framework futures versions du peuvent introduire de nouvelles stratégies d’équité.Future versions of the .NET Framework.NET Framework may introduce new fairness policies.

  • Un thread qui tente d’entrer en mode de mise à niveau bloque s’il existe déjà un thread en mode de mise à niveau, si des threads attendent pour entrer en mode écriture, ou s’il existe un seul thread en mode écriture.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 qui tente d’entrer en mode écriture bloque s’il existe un thread dans l’un des trois modes.A thread that tries to enter write mode blocks if there is a thread in any of the three modes.

Mise à niveau et rétrogradation de verrousUpgrading and Downgrading Locks

Le mode de mise à niveau est prévu dans les cas où un thread lit généralement à partir de la ressource protégée, mais peut avoir besoin d’y écrire si une condition est remplie.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 qui est entré dans ReaderWriterLockSlim le mode de mise à niveau dispose d’un accès en lecture à la ressource protégée et peut être mis EnterWriteLock à TryEnterWriteLock niveau vers le mode écriture en appelant les méthodes ou.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. Étant donné qu’il ne peut y avoir qu’un seul thread en mode de mise à niveau à la fois, la mise à niveau vers le mode écriture ne peut pas se bloquer lorsque la récursivité n’est pas autorisée, qui est la stratégie par défaut.Because there can be only one thread in upgradeable mode at a time, upgrading to write mode cannot deadlock when recursion is not allowed, which is the default policy.

Important

Quelle que soit la stratégie de récurrence, un thread qui est entré initialement en mode lecture n’est pas autorisé à effectuer une mise à niveau vers le mode de mise à niveau ou le mode écriture, car ce modèle crée une probabilité forte de blocages.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. Par exemple, si deux threads en mode lecture essaient tous les deux d’entrer en mode écriture, ils se bloquent.For example, if two threads in read mode both try to enter write mode, they will deadlock. Le mode de mise à niveau est conçu pour éviter de tels blocages.Upgradeable mode is designed to avoid such deadlocks.

Si d’autres threads sont en mode lecture, le thread qui met à niveau les blocs.If there are other threads in read mode, the thread that is upgrading blocks. Pendant que le thread est bloqué, les autres threads qui essaient d’entrer en mode lecture sont bloqués.While the thread is blocked, other threads that try to enter read mode are blocked. Lorsque tous les threads ont quitté le mode lecture, le thread extensible bloqué passe en mode écriture.When all threads have exited from read mode, the blocked upgradeable thread enters write mode. Si d’autres threads attendent pour entrer en mode écriture, ils restent bloqués, car le thread unique qui est en mode de mise à niveau les empêche d’obtenir un accès exclusif à la ressource.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.

Lorsque le thread en mode de mise à niveau quitte le mode écriture, les autres threads qui attendent pour entrer en mode lecture peuvent le faire, sauf si des threads attendent pour entrer en mode écriture.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. Le thread en mode de mise à niveau peut mettre à niveau et rétrograder indéfiniment, tant qu’il s’agit du seul thread qui écrit dans la ressource protégée.The thread in upgradeable mode can upgrade and downgrade indefinitely, as long as it is the only thread that writes to the protected resource.

Important

Si vous permettez à plusieurs threads d’entrer en mode écriture ou de mise à niveau, vous ne devez pas autoriser un thread à monopoliser le mode de mise à niveau.If you allow multiple threads to enter write mode or upgradeable mode, you must not allow one thread to monopolize upgradeable mode. Dans le cas contraire, les threads qui essaient d’entrer directement en mode écriture sont bloqués indéfiniment, et Pendant qu’ils sont bloqués, les autres threads ne peuvent pas passer en mode lecture.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 thread en mode de mise à niveau peut passer à une version antérieure en EnterReadLock mode lecture en appelant d' ExitUpgradeableReadLock abord la méthode, puis en appelant la méthode.A thread in upgradeable mode can downgrade to read mode by first calling the EnterReadLock method and then calling the ExitUpgradeableReadLock method. Ce modèle de rétrogradation est autorisé pour toutes les stratégies de récurrence des verrous NoRecursion, même.This downgrade pattern is allowed for all lock recursion policies, even NoRecursion.

Après une rétrogradation vers le mode lecture, un thread ne peut pas repasser en mode de mise à niveau tant qu’il n’a pas quitté le mode lecture.After downgrading to read mode, a thread cannot reenter upgradeable mode until it has exited from read mode.

Entrée récursive du verrouEntering the Lock Recursively

Vous pouvez créer un ReaderWriterLockSlim qui prend en charge l’entrée de verrou récursif ReaderWriterLockSlim(LockRecursionPolicy) en utilisant le constructeur qui spécifie la LockRecursionPolicy.SupportsRecursionstratégie de verrouillage et en spécifiant.You can create a ReaderWriterLockSlim that supports recursive lock entry by using the ReaderWriterLockSlim(LockRecursionPolicy) constructor that specifies lock policy, and specifying LockRecursionPolicy.SupportsRecursion.

Notes

L’utilisation de la récursivité n’est pas recommandée pour un nouveau développement, car elle introduit des complications inutiles et rend votre code plus sujet aux blocages.The use of recursion is not recommended for new development, because it introduces unnecessary complications and makes your code more prone to deadlocks.

Pour un ReaderWriterLockSlim qui autorise la récursivité, les éléments suivants peuvent être déclarés à propos des modes qu’un thread peut entrer:For a ReaderWriterLockSlim that allows recursion, the following can be said about the modes a thread can enter:

  • Un thread en mode lecture peut entrer en mode lecture de manière récursive, mais ne peut pas passer en mode écriture ou en mode de mise à niveau.A thread in read mode can enter read mode recursively, but cannot enter write mode or upgradeable mode. Si elle tente de le faire, une LockRecursionException exception est levée.If it tries to do this, a LockRecursionException is thrown. Le fait d’entrer en mode lecture, puis d’entrer en mode écriture ou de mode de mise à niveau est un modèle avec une forte probabilité d’interblocages. il n’est donc pas autorisé.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. Comme nous l’avons vu précédemment, le mode de mise à niveau est fourni dans les cas où il est nécessaire de mettre à niveau un verrou.As discussed earlier, upgradeable mode is provided for cases where it is necessary to upgrade a lock.

  • Un thread en mode de mise à niveau peut passer en mode écriture et/ou en mode lecture et peut entrer l’un des trois modes de manière récursive.A thread in upgradeable mode can enter write mode and/or read mode, and can enter any of the three modes recursively. Toutefois, une tentative d’entrer en mode écriture bloque si d’autres threads sont en mode lecture.However, an attempt to enter write mode blocks if there are other threads in read mode.

  • Un thread en mode écriture peut passer en mode lecture et/ou en mode de mise à niveau, et peut entrer l’un des trois modes de manière récursive.A thread in write mode can enter read mode and/or upgradeable mode, and can enter any of the three modes recursively.

  • Un thread qui n’a pas entré le verrou peut entrer dans n’importe quel mode.A thread that has not entered the lock can enter any mode. Cette tentative peut se bloquer pour les mêmes raisons qu’une tentative d’entrée d’un verrou non récursif.This attempt can block for the same reasons as an attempt to enter a non-recursive lock.

Un thread peut quitter les modes entrés dans n’importe quel ordre, à condition qu’il quitte chaque mode exactement autant de fois qu’il a entré ce mode.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 thread essaie de quitter un mode trop souvent, ou de quitter un mode qu’il n’a pas entré, SynchronizationLockException une exception est levée.If a thread tries to exit a mode too many times, or to exit a mode it has not entered, a SynchronizationLockException is thrown.

États de verrouillageLock States

Il peut s’avérer utile de considérer le verrou en termes de son état.You may find it useful to think of the lock in terms of its states. Un ReaderWriterLockSlim peut être dans l’un des quatre États suivants: non entré, lecture, mise à niveau et écriture.A ReaderWriterLockSlim can be in one of four states: not entered, read, upgrade, and write.

  • Non entré: Dans cet État, aucun thread n’est entré dans le verrou (ou tous les threads ont quitté le verrou).Not entered: In this state, no threads have entered the lock (or all threads have exited the lock).

  • Lecture : Dans cet État, un ou plusieurs threads ont entré le verrou pour l’accès en lecture à la ressource protégée.Read: In this state, one or more threads have entered the lock for read access to the protected resource.

    Notes

    Un thread peut entrer le verrou en mode lecture à l’aide EnterReadLock des TryEnterReadLock méthodes ou, ou en rétrograder du mode de mise à niveau.A thread can enter the lock in read mode by using the EnterReadLock or TryEnterReadLock methods, or by downgrading from upgradeable mode.

  • Installation Dans cet État, un thread a entré le verrou pour l’accès en lecture avec l’option de mise à niveau vers l’accès en écriture (autrement dit, en mode de mise à niveau) et zéro ou plusieurs threads ont entré le verrou pour l’accès en lecture.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. Un seul thread à la fois peut entrer le verrou avec l’option de mise à niveau; les threads supplémentaires qui essaient d’entrer en mode de mise à niveau sont bloqués.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.

  • Écriture : Dans cet État, un thread a entré le verrou pour l’accès en écriture à la ressource protégée.Write: In this state, one thread has entered the lock for write access to the protected resource. Ce thread a la possession exclusive du verrou.That thread has exclusive possession of the lock. Tout autre thread qui tente d’entrer le verrou pour une raison quelconque est bloqué.Any other thread that tries to enter the lock for any reason is blocked.

Le tableau suivant décrit les transitions entre les États de verrou, pour les verrous qui n’autorisent pas la récursivité t , lorsqu’un thread effectue l’action décrite dans la colonne la plus à gauche.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. Au moment où il prend l’action, t n’a aucun mode.At the time it takes the action, t has no mode. (Le cas particulier où t est en mode de mise à niveau est décrit dans les notes de bas du tableau.) La ligne supérieure décrit l’état de départ du verrou.(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. Les cellules décrivent ce qui arrive au thread et affichent les modifications apportées à l’état de verrouillage entre parenthèses.The cells describe what happens to the thread, and show changes to the lock state in parentheses.

Non entré (N)Not entered (N) Lecture (R)Read (R) Mise à niveau (U)Upgrade (U) Écriture (W)Write (W)
tentre en mode lecturet enters read mode tentre (R).t enters (R). tbloque si les threads sont en attente de mode écriture; Sinon, t entre.t blocks if threads are waiting for write mode; otherwise, t enters. tbloque si les threads sont en attente de mode écriture; Sinon, t entre. 1t blocks if threads are waiting for write mode; otherwise, t enters.1 tblocs.t blocks.
tpasse en mode de mise à niveaut enters upgradeable mode tentre (U).t enters (U). tbloque si les threads sont en attente de mode écriture ou de mode de mise à niveau; Sinon, t entre (U).t blocks if threads are waiting for write mode or upgrade mode; otherwise, t enters (U). tblocs.t blocks. tblocs.t blocks.
tpasse en mode écrituret enters write mode tentre (W).t enters (W). tblocs.t blocks. tblocs. 2t blocks.2 tblocs.t blocks.

1 si t démarre en mode de mise à niveau, il passe en mode lecture.1 If t starts out in upgradeable mode, it enters read mode. Cette action ne bloque jamais.This action never blocks. L’état du verrou ne change pas.The lock state does not change. (Le thread peut ensuite effectuer une rétrogradation vers le mode de lecture en quittant le mode de mise à niveau.)(The thread can then complete a downgrade to read mode by exiting upgradeable mode.)

2 si t démarre en mode de mise à niveau, il bloque s’il existe des threads en mode lecture.2 If t starts out in upgradeable mode, it blocks if there are threads in read mode. Dans le cas contraire, il est mis à niveau en mode écriture.Otherwise it upgrades to write mode. L’état de verrouillage passe à Write (W).The lock state changes to Write (W). Si t bloque, car il y a des threads en mode lecture, il passe en mode écriture dès que le dernier thread quitte le mode lecture, même si des threads attendent pour entrer en mode écriture.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.

Quand un changement d’État se produit parce qu’un thread quitte le verrou, le thread suivant à réveiller est sélectionné comme suit:When a state change occurs because a thread exits the lock, the next thread to be awakened is selected as follows:

  • Tout d’abord, un thread qui attend le mode écriture et qui est déjà en mode de mise à niveau (il ne peut y avoir qu’un seul thread de ce type).First, a thread that is waiting for write mode and is already in upgradeable mode (there can be at most one such thread).

  • Échec, un thread qui attend le mode écriture.Failing that, a thread that is waiting for write mode.

  • En cas d’échec, un thread en attente de mode de mise à niveau.Failing that, a thread that is waiting for upgradeable mode.

  • En cas d’échec, tous les threads sont en attente de lecture.Failing that, all threads that are waiting for read mode.

L’état suivant du verrou est toujours Write (W) dans les deux premiers cas et Upgrade (U) dans le troisième cas, quel que soit l’état du verrou lorsque le thread de sortie a déclenché le changement d’État.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. Dans le dernier cas, l’état du verrou est Upgrade (U) s’il existe un thread en mode de mise à niveau après le changement d’État, et Read (R) dans le cas contraire, quel que soit l’état précédent.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.

Constructeurs

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

Initialise une nouvelle instance de la classe ReaderWriterLockSlim avec des valeurs de propriété par défaut.Initializes a new instance of the ReaderWriterLockSlim class with default property values.

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

Initialise une nouvelle instance de la classe ReaderWriterLockSlim, en spécifiant la stratégie de récurrence du verrou.Initializes a new instance of the ReaderWriterLockSlim class, specifying the lock recursion policy.

Propriétés

CurrentReadCount CurrentReadCount CurrentReadCount CurrentReadCount

Obtient le nombre total de threads uniques qui ont entré le verrou en mode lecture.Gets the total number of unique threads that have entered the lock in read mode.

IsReadLockHeld IsReadLockHeld IsReadLockHeld IsReadLockHeld

Obtient une valeur qui indique si le thread actuel a entré le verrou en mode lecture.Gets a value that indicates whether the current thread has entered the lock in read mode.

IsUpgradeableReadLockHeld IsUpgradeableReadLockHeld IsUpgradeableReadLockHeld IsUpgradeableReadLockHeld

Obtient une valeur qui indique si le thread actuel a entré le verrou en mode de mise à niveau.Gets a value that indicates whether the current thread has entered the lock in upgradeable mode.

IsWriteLockHeld IsWriteLockHeld IsWriteLockHeld IsWriteLockHeld

Obtient une valeur qui indique si le thread actuel a entré le verrou en mode écriture.Gets a value that indicates whether the current thread has entered the lock in write mode.

RecursionPolicy RecursionPolicy RecursionPolicy RecursionPolicy

Obtient une valeur qui indique la stratégie de récurrence pour l'objet ReaderWriterLockSlim actuel.Gets a value that indicates the recursion policy for the current ReaderWriterLockSlim object.

RecursiveReadCount RecursiveReadCount RecursiveReadCount RecursiveReadCount

Obtient le nombre de fois où le thread actuel a entré le verrou en mode lecture, comme une indication de récurrence.Gets the number of times the current thread has entered the lock in read mode, as an indication of recursion.

RecursiveUpgradeCount RecursiveUpgradeCount RecursiveUpgradeCount RecursiveUpgradeCount

Obtient le nombre de fois où le thread actuel a entré le verrou en mode de mise à niveau, comme une indication de récurrence.Gets the number of times the current thread has entered the lock in upgradeable mode, as an indication of recursion.

RecursiveWriteCount RecursiveWriteCount RecursiveWriteCount RecursiveWriteCount

Obtient le nombre de fois où le thread actuel a entré le verrou en mode écriture, comme une indication de récurrence.Gets the number of times the current thread has entered the lock in write mode, as an indication of recursion.

WaitingReadCount WaitingReadCount WaitingReadCount WaitingReadCount

Obtient le nombre total de threads qui attendent pour entrer le verrou en mode lecture.Gets the total number of threads that are waiting to enter the lock in read mode.

WaitingUpgradeCount WaitingUpgradeCount WaitingUpgradeCount WaitingUpgradeCount

Obtient le nombre total de threads qui attendent pour entrer le verrou en mode de mise à niveau.Gets the total number of threads that are waiting to enter the lock in upgradeable mode.

WaitingWriteCount WaitingWriteCount WaitingWriteCount WaitingWriteCount

Obtient le nombre total de threads qui attendent pour entrer le verrou en mode écriture.Gets the total number of threads that are waiting to enter the lock in write mode.

Méthodes

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

Libère toutes les ressources utilisées par l'instance actuelle de la classe ReaderWriterLockSlim.Releases all resources used by the current instance of the ReaderWriterLockSlim class.

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

Essaie d'entrer le verrou en mode lecture.Tries to enter the lock in read mode.

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

Essaie d'entrer le verrou en mode de mise à niveau.Tries to enter the lock in upgradeable mode.

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

Essaie d'entrer le verrou en mode écriture.Tries to enter the lock in write mode.

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

Détermine si l'objet spécifié est identique à l'objet actuel.Determines whether the specified object is equal to the current object.

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

Réduit le nombre de récurrences pour le mode lecture, et quitte le mode lecture si le compte résultant est 0 (zéro).Reduces the recursion count for read mode, and exits read mode if the resulting count is 0 (zero).

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

Réduit le nombre de récurrences pour le mode de mise à niveau, et quitte le mode de mise à niveau si le compte résultant est 0 (zéro).Reduces the recursion count for upgradeable mode, and exits upgradeable mode if the resulting count is 0 (zero).

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

Réduit le nombre de récurrences pour le mode écriture, et quitte le mode écriture si le compte résultant est 0 (zéro).Reduces the recursion count for write mode, and exits write mode if the resulting count is 0 (zero).

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

Fait office de fonction de hachage par défaut.Serves as the default hash function.

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

Obtient le Type de l'instance actuelle.Gets the Type of the current instance.

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

Crée une copie superficielle de l'objet Object actuel.Creates a shallow copy of the current Object.

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

Retourne une chaîne qui représente l'objet actuel.Returns a string that represents the current object.

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

Essaie d'entrer le verrou en mode lecture, avec un délai d'attente entier facultatif.Tries to enter the lock in read mode, with an optional integer time-out.

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

Essaie d'entrer le verrou en mode lecture, avec un délai d'attente facultatif.Tries to enter the lock in read mode, with an optional time-out.

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

Essaie d'entrer le verrou en mode de mise à niveau, avec un délai d'attente facultatif.Tries to enter the lock in upgradeable mode, with an optional time-out.

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

Essaie d'entrer le verrou en mode de mise à niveau, avec un délai d'attente facultatif.Tries to enter the lock in upgradeable mode, with an optional time-out.

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

Essaie d'entrer le verrou en mode écriture, avec un délai d'attente facultatif.Tries to enter the lock in write mode, with an optional time-out.

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

Essaie d'entrer le verrou en mode écriture, avec un délai d'attente facultatif.Tries to enter the lock in write mode, with an optional time-out.

S’applique à

Cohérence de thread

Ce type est thread-safe.This type is thread safe.