Exporter (0) Imprimer
Développer tout
Cet article a fait l'objet d'une traduction automatique. Déplacez votre pointeur sur les phrases de l'article pour voir la version originale de ce texte. Informations supplémentaires.
Traduction
Source

ReaderWriterLock, classe

Définit un verrou qui prend en charge les writers uniques et les lecteurs multiples.

Espace de noms :  System.Threading
Assembly :  mscorlib (dans mscorlib.dll)

[ComVisibleAttribute(true)]
[HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true, 
	ExternalThreading = true)]
public sealed class ReaderWriterLock : CriticalFinalizerObject

Le type ReaderWriterLock expose les membres suivants.

  NomDescription
Méthode publiqueReaderWriterLockInitialise une nouvelle instance de la classe ReaderWriterLock.
Début

  NomDescription
Propriété publiqueIsReaderLockHeldObtient une valeur indiquant si le thread en cours détient un verrou de lecteur.
Propriété publiqueIsWriterLockHeldObtient une valeur indiquant si le thread en cours détient le verrou de writer.
Propriété publiqueWriterSeqNumObtient le numéro de séquence actuel.
Début

  NomDescription
Méthode publiqueAcquireReaderLock(Int32)Acquiert un verrou de lecteur en utilisant une valeur Int32 comme délai d'attente.
Méthode publiqueAcquireReaderLock(TimeSpan)Acquiert un verrou de lecteur en utilisant une valeur TimeSpan comme délai d'attente.
Méthode publiqueAcquireWriterLock(Int32)Acquiert un verrou de writer en utilisant une valeur Int32 comme délai d'attente.
Méthode publiqueAcquireWriterLock(TimeSpan)Acquiert un verrou de writer en utilisant une valeur TimeSpan comme délai d'attente.
Méthode publiqueAnyWritersSinceIndique si le verrou de writer a été accordé à un thread depuis l'obtention du numéro de séquence.
Méthode publiqueDowngradeFromWriterLockRestaure le verrou du thread à l'état qu'il avait avant l'appel à UpgradeToWriterLock.
Méthode publiqueEquals(Object)Détermine si l'objet spécifié est identique à l'objet actuel. (Hérité de Object.)
Méthode publiqueGetHashCodeSert de fonction de hachage par défaut. (Hérité de Object.)
Méthode publiqueGetTypeObtient le Type de l'instance actuelle. (Hérité de Object.)
Méthode publiqueReleaseLockLibère le verrou quel que soit le nombre de fois où il a été acquis par le thread.
Méthode publiqueReleaseReaderLockDécrémente le nombre de verrous.
Méthode publiqueReleaseWriterLockDécrémente le nombre de verrous sur le verrou de writer.
Méthode publiqueRestoreLockRestaure l'état de verrou du thread au moment précédant l'appel à ReleaseLock.
Méthode publiqueToStringRetourne une chaîne qui représente l'objet actif. (Hérité de Object.)
Méthode publiqueUpgradeToWriterLock(Int32)Met à niveau un verrou de lecteur vers le verrou de writer en utilisant une valeur Int32 pour définir le délai d'attente.
Méthode publiqueUpgradeToWriterLock(TimeSpan)Met à niveau un verrou de lecteur vers le verrou de writer en utilisant une valeur TimeSpan pour définir le délai d'attente.
Début

Remarque importanteImportant

Le .NET Framework a deux verrous de writer de lecteur, ReaderWriterLockSlimet ReaderWriterLock. ReaderWriterLockSlim est recommandé pout tout nouveau développement. ReaderWriterLockSlim est semblable à ReaderWriterLock, mais les règles de récurrence et de mise à niveau et rétrogradation de l'état de verrou sont simplifiées. ReaderWriterLockSlim évite de nombreux cas d'interblocage potentiel. De plus, la performance de ReaderWriterLockSlim est considérablement meilleure que ReaderWriterLock.

ReaderWriterLock sert à synchroniser l'accès à une ressource. Il permet à tout moment un accès en lecture simultané à plusieurs threads ou un accès en écriture à un seul thread. Dans le cas d'une ressource rarement modifiée, un ReaderWriterLock offre un meilleur débit que le simple verrou permettant un seul accès à la fois, comme Monitor.

ReaderWriterLock est le plus efficace dans le cas où la plupart des accès sont des accès en lecture et où les accès en écriture sont rares et de courte durée. Les lecteurs multiples alternent avec les writers uniques de sorte qui ni les lecteurs ni les writers ne sont bloqués pendant de longues périodes.

RemarqueRemarque

Le maintien de verrous de lecteur ou de writer pendant de longues périodes retarde l'exécution d'autres threads. Pour optimiser les performances, envisagez de restructurer votre application afin de limiter la durée des accès en écriture.

Un thread peut détenir un verrou de lecteur ou un verrou de writer mais pas les deux en même temps. Au lieu de libérer un verrou de lecteur pour acquérir le verrou de writer, vous pouvez utiliser UpgradeToWriterLock et DowngradeFromWriterLock.

Des demandes de verrou récursives font augmenter le nombre de verrous sur un verrou.

Les lecteurs et les writers sont placés dans des files d'attente séparées. Lorsqu'un thread libère le verrou de writer, des verrous de lecteur sont octroyés à tous les threads en attente dans la file de lecteurs ; lorsque tous ces verrous de lecteur ont été libérés, le verrou de writer est octroyé au thread suivant de la file d'attente de writers, s'il y en a un, et ainsi de suite. En d'autres termes, ReaderWriterLock alterne entre une collection de lecteurs et un seul writer.

Pendant qu'un thread de la file d'attente des writers attend que des verrous de lecteur actifs soient libérés, les threads demandant de nouveaux verrous de lecteur s'accumulent dans la file d'attente des lecteurs. Leurs demandes ne sont pas acceptées même s'ils peuvent partager un accès simultané avec des détenteurs de verrous de lecteur existants ; de cette façon les writers sont mieux protégés contre un verrouillage indéfini par les lecteurs.

La plupart des méthodes d'acquisition de verrous sur un ReaderWriterLock acceptent des valeurs d'expiration. Utilisez les valeurs d'expiration pour éviter les interblocages dans votre application. Par exemple, un thread peut acquérir le verrou de writer sur une ressource puis demander un verrou de lecteur sur une seconde ressource ; dans l'intervalle, un autre thread peut acquérir le verrou de writer sur la seconde ressource et demander un verrou de lecteur sur la première. À moins de définir des valeurs d'expiration, les threads se bloquent mutuellement.

Si le délai d'attente expire et que la demande de verrou n'a pas été accordée, la méthode retourne le contrôle au thread appelant en levant une ApplicationException. Un thread peut intercepter cette exception et décider de la prochaine action à effectuer.

Les délais d'attente sont exprimés en millisecondes. Si vous utilisez un System.TimeSpan pour spécifier le délai d'attente, la valeur utilisée est le total des millisecondes entières représentées par TimeSpan. Le tableau suivant indique les valeurs de délai d'attente valides en millisecondes.

Valeur

Description

-1

Le thread attend jusqu'à ce que le verrou soit acquis, quelle que soit la durée nécessaire. Pour les méthodes qui spécifient des délais d'expiration entiers, la constante Infinite peut être utilisée.

0

Le thread n'attend pas pour acquérir le verrou. Si le verrou ne peut pas être acquis immédiatement, la méthode retourne.

>0

Nombre de millisecondes à attendre.

À l'exception de -1, les délais d'attente négatifs ne sont pas admis. Si vous spécifiez un entier négatif autre que -1, un délai d'attente égal à zéro est utilisé. (Autrement dit, la méthode retourne sans attendre si le verrou ne peut pas être acquis immédiatement.) Si vous spécifiez un TimeSpan qui représente un nombre négatif de millisecondes autre que -1, le système lève une ArgumentOutOfRangeException.

RemarqueRemarque

L'attribut HostProtectionAttribute appliqué à ce type ou membre a la valeur de propriété Resources suivante : Synchronization | ExternalThreading. HostProtectionAttribute n'affecte pas les applications bureautiques (qui sont généralement démarrées en double-cliquant sur une icône, en tapant une commande ou en entrant une URL dans un navigateur). Pour plus d'informations, consultez la classe HostProtectionAttribute ou Attributs de programmation et de protection des hôtes SQL Server.

L'exemple suivant montre comment utiliser un ReaderWriterLock pour protéger une ressource partagée qui est lue simultanément et est écrite exclusivement par plusieurs threads.


// This example shows a ReaderWriterLock protecting a shared
// resource that is read concurrently and written exclusively
// by multiple threads.

// The complete code is located in the ReaderWriterLock
// class topic.
using System;
using System.Threading;

public class Test
{
    // Declaring the ReaderWriterLock at the class level
    // makes it visible to all threads.
    static ReaderWriterLock rwl = new ReaderWriterLock();
    // For this example, the shared resource protected by the
    // ReaderWriterLock is just an integer.
    static int resource = 0;

    const int numThreads = 26;
    static bool running = true;
    static Random rnd = new Random();

    // Statistics.
    static int readerTimeouts = 0;
    static int writerTimeouts = 0;
    static int reads = 0;
    static int writes = 0;

    public static void Main(string[] args)
    {
        // Start a series of threads. Each thread randomly
        // performs reads and writes on the shared resource.
        Thread[] t = new Thread[numThreads];
        for (int i = 0; i < numThreads; i++)
        {
            t[i] = new Thread(new ThreadStart(ThreadProc));
            t[i].Name = new String(Convert.ToChar(i + 65), 1);
            t[i].Start();
            if (i > 10)
                Thread.Sleep(300);
        }

        // Tell the threads to shut down, then wait until they all
        // finish.
        running = false;
        for (int i = 0; i < numThreads; i++)
        {
            t[i].Join();
        }

        // Display statistics.
        Console.WriteLine("\r\n{0} reads, {1} writes, {2} reader time-outs, {3} writer time-outs.",
            reads, writes, readerTimeouts, writerTimeouts);
        Console.WriteLine("Press ENTER to exit.");
        Console.ReadLine();
    }

    static void ThreadProc()
    {
        // As long as a thread runs, it randomly selects
        // various ways to read and write from the shared 
        // resource. Each of the methods demonstrates one 
        // or more features of ReaderWriterLock.
        while (running)
        {
            double action = rnd.NextDouble();
            if (action < .8)
                ReadFromResource(10);
            else if (action < .81)
                ReleaseRestore(50);
            else if (action < .90)
                UpgradeDowngrade(100);
            else
                WriteToResource(100);
        }
    }

    // Shows how to request and release a reader lock, and
    // how to handle time-outs.
    static void ReadFromResource(int timeOut)
    {
        try
        {
            rwl.AcquireReaderLock(timeOut);
            try
            {
                // It is safe for this thread to read from
                // the shared resource.
                Display("reads resource value " + resource); 
                Interlocked.Increment(ref reads);
            }        
            finally
            {
                // Ensure that the lock is released.
                rwl.ReleaseReaderLock();
            }
        }
        catch (ApplicationException)
        {
            // The reader lock request timed out.
            Interlocked.Increment(ref readerTimeouts);
        }
    }

    // Shows how to request and release the writer lock, and
    // how to handle time-outs.
    static void WriteToResource(int timeOut)
    {
        try
        {
            rwl.AcquireWriterLock(timeOut);
            try
            {
                // It is safe for this thread to read or write
                // from the shared resource.
                resource = rnd.Next(500);
                Display("writes resource value " + resource);
                Interlocked.Increment(ref writes);
            }        
            finally
            {
                // Ensure that the lock is released.
                rwl.ReleaseWriterLock();
            }
        }
        catch (ApplicationException)
        {
            // The writer lock request timed out.
            Interlocked.Increment(ref writerTimeouts);
        }
    }

    // Shows how to request a reader lock, upgrade the
    // reader lock to the writer lock, and downgrade to a
    // reader lock again.
    static void UpgradeDowngrade(int timeOut)
    {
        try
        {
            rwl.AcquireReaderLock(timeOut);
            try
            {
                // It is safe for this thread to read from
                // the shared resource.
                Display("reads resource value " + resource); 
                Interlocked.Increment(ref reads);

                // If it is necessary to write to the resource,
                // you must either release the reader lock and 
                // then request the writer lock, or upgrade the
                // reader lock. Note that upgrading the reader lock
                // puts the thread in the write queue, behind any
                // other threads that might be waiting for the 
                // writer lock.
                try
                {
                    LockCookie lc = rwl.UpgradeToWriterLock(timeOut);
                    try
                    {
                        // It is safe for this thread to read or write
                        // from the shared resource.
                        resource = rnd.Next(500);
                        Display("writes resource value " + resource);
                        Interlocked.Increment(ref writes);
                    }        
                    finally
                    {
                        // Ensure that the lock is released.
                        rwl.DowngradeFromWriterLock(ref lc);
                    }
                }
                catch (ApplicationException)
                {
                    // The upgrade request timed out.
                    Interlocked.Increment(ref writerTimeouts);
                }

                // When the lock has been downgraded, it is 
                // still safe to read from the resource.
                Display("reads resource value " + resource); 
                Interlocked.Increment(ref reads);
            }        
            finally
            {
                // Ensure that the lock is released.
                rwl.ReleaseReaderLock();
            }
        }
        catch (ApplicationException)
        {
            // The reader lock request timed out.
            Interlocked.Increment(ref readerTimeouts);
        }
    }

    // Shows how to release all locks and later restore
    // the lock state. Shows how to use sequence numbers
    // to determine whether another thread has obtained
    // a writer lock since this thread last accessed the
    // resource.
    static void ReleaseRestore(int timeOut)
    {
        int lastWriter;

        try
        {
            rwl.AcquireReaderLock(timeOut);
            try
            {
                // It is safe for this thread to read from
                // the shared resource. Cache the value. (You
                // might do this if reading the resource is
                // an expensive operation.)
                int resourceValue = resource;
                Display("reads resource value " + resourceValue); 
                Interlocked.Increment(ref reads);

                // Save the current writer sequence number.
                lastWriter = rwl.WriterSeqNum;

                // Release the lock, and save a cookie so the
                // lock can be restored later.
                LockCookie lc = rwl.ReleaseLock();

                // Wait for a random interval (up to a 
                // quarter of a second), and then restore
                // the previous state of the lock. Note that
                // there is no time-out on the Restore method.
                Thread.Sleep(rnd.Next(250));
                rwl.RestoreLock(ref lc);

                // Check whether other threads obtained the
                // writer lock in the interval. If not, then
                // the cached value of the resource is still
                // valid.
                if (rwl.AnyWritersSince(lastWriter))
                {
                    resourceValue = resource;
                    Interlocked.Increment(ref reads);
                    Display("resource has changed " + resourceValue);
                }
                else
                {
                    Display("resource has not changed " + resourceValue);
                }
            }        
            finally
            {
                // Ensure that the lock is released.
                rwl.ReleaseReaderLock();
            }
        }
        catch (ApplicationException)
        {
            // The reader lock request timed out.
            Interlocked.Increment(ref readerTimeouts);
        }
    }

    // Helper method briefly displays the most recent
    // thread action. Comment out calls to Display to 
    // get a better idea of throughput.
    static void Display(string msg)
    {
        Console.Write("Thread {0} {1}.       \r", Thread.CurrentThread.Name, msg);
    }
}


.NET Framework

Pris en charge dans : 4.5.2, 4.5.1, 4.5, 4, 3.5, 3.0, 2.0, 1.1, 1.0

.NET Framework Client Profile

Pris en charge dans : 4, 3.5 SP1

Windows Phone 8.1, Windows Phone 8, Windows 8.1, Windows Server 2012 R2, Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (rôle principal du serveur non pris en charge), Windows Server 2008 R2 (rôle principal du serveur pris en charge avec SP1 ou version ultérieure ; Itanium non pris en charge)

Le .NET Framework ne prend pas en charge toutes les versions de chaque plateforme. Pour obtenir la liste des versions prises en charge, consultez Configuration requise du .NET Framework.

Ce type est thread-safe.

Ajouts de la communauté

AJOUTER
Afficher:
© 2015 Microsoft