Interlocked Classe

Définition

Fournit des opérations atomiques pour des variables partagées par plusieurs threads.

public ref class Interlocked abstract sealed
public ref class Interlocked sealed
public static class Interlocked
public sealed class Interlocked
type Interlocked = class
Public Class Interlocked
Public NotInheritable Class Interlocked
Héritage
Interlocked

Exemples

L’exemple de code suivant montre un mécanisme de verrouillage de ressources thread-safe.

using namespace System;
using namespace System::Threading;

const int numThreads = 10;
const int numThreadIterations = 5;
ref class MyInterlockedExchangeExampleClass
{
public:
   static void MyThreadProc()
   {
      for ( int i = 0; i < numThreadIterations; i++ )
      {
         UseResource();
         
         //Wait 1 second before next attempt.
         Thread::Sleep( 1000 );

      }
   }


private:
   //A simple method that denies reentrancy.
   static bool UseResource()
   {
      
      //0 indicates that the method is not in use.
      if ( 0 == Interlocked::Exchange( usingResource, 1 ) )
      {
         Console::WriteLine( " {0} acquired the lock", Thread::CurrentThread->Name );
         
         //Code to access a resource that is not thread safe would go here.
         //Simulate some work
         Thread::Sleep( 500 );
         Console::WriteLine( " {0} exiting lock", Thread::CurrentThread->Name );
         
         //Release the lock
         Interlocked::Exchange( usingResource, 0 );
         return true;
      }
      else
      {
         Console::WriteLine( " {0} was denied the lock", Thread::CurrentThread->Name );
         return false;
      }
   }


   //0 for false, 1 for true.
   static int usingResource;
};

int main()
{
   Thread^ myThread;
   Random^ rnd = gcnew Random;
   for ( int i = 0; i < numThreads; i++ )
   {
      myThread = gcnew Thread( gcnew ThreadStart( MyInterlockedExchangeExampleClass::MyThreadProc ) );
      myThread->Name = String::Format( "Thread {0}", i + 1 );
      
      //Wait a random amount of time before starting next thread.
      Thread::Sleep( rnd->Next( 0, 1000 ) );
      myThread->Start();

   }
}
using System;
using System.Threading;

namespace InterlockedExchange_Example
{
    class MyInterlockedExchangeExampleClass
    {
        //0 for false, 1 for true.
        private static int usingResource = 0;

        private const int numThreadIterations = 5;
        private const int numThreads = 10;

        static void Main()
        {
            Thread myThread;
            Random rnd = new Random();

            for(int i = 0; i < numThreads; i++)
            {
                myThread = new Thread(new ThreadStart(MyThreadProc));
                myThread.Name = String.Format("Thread{0}", i + 1);
            
                //Wait a random amount of time before starting next thread.
                Thread.Sleep(rnd.Next(0, 1000));
                myThread.Start();
            }
        }

        private static void MyThreadProc()
        {
            for(int i = 0; i < numThreadIterations; i++)
            {
                UseResource();
            
                //Wait 1 second before next attempt.
                Thread.Sleep(1000);
            }
        }

        //A simple method that denies reentrancy.
        static bool UseResource()
        {
            //0 indicates that the method is not in use.
            if(0 == Interlocked.Exchange(ref usingResource, 1))
            {
                Console.WriteLine("{0} acquired the lock", Thread.CurrentThread.Name);
            
                //Code to access a resource that is not thread safe would go here.
            
                //Simulate some work
                Thread.Sleep(500);

                Console.WriteLine("{0} exiting lock", Thread.CurrentThread.Name);
            
                //Release the lock
                Interlocked.Exchange(ref usingResource, 0);
                return true;
            }
            else
            {
                Console.WriteLine("   {0} was denied the lock", Thread.CurrentThread.Name);
                return false;
            }
        }
    }
}
Imports System.Threading

Namespace InterlockedExchange_Example
    Class MyInterlockedExchangeExampleClass
        '0 for false, 1 for true.
        Private Shared usingResource As Integer = 0

        Private Const numThreadIterations As Integer = 5
        Private Const numThreads As Integer = 10

        <MTAThread> _
        Shared Sub Main()
            Dim myThread As Thread
            Dim rnd As New Random()

            Dim i As Integer
            For i = 0 To numThreads - 1
                myThread = New Thread(AddressOf MyThreadProc)
                myThread.Name = String.Format("Thread{0}", i + 1)

                'Wait a random amount of time before starting next thread.
                Thread.Sleep(rnd.Next(0, 1000))
                myThread.Start()
            Next i
        End Sub

        Private Shared Sub MyThreadProc()
            Dim i As Integer
            For i = 0 To numThreadIterations - 1
                UseResource()

                'Wait 1 second before next attempt.
                Thread.Sleep(1000)
            Next i
        End Sub 

        'A simple method that denies reentrancy.
        Shared Function UseResource() As Boolean
            '0 indicates that the method is not in use.
            If 0 = Interlocked.Exchange(usingResource, 1) Then
                Console.WriteLine("{0} acquired the lock", Thread.CurrentThread.Name)

                'Code to access a resource that is not thread safe would go here.
                'Simulate some work
                Thread.Sleep(500)

                Console.WriteLine("{0} exiting lock", Thread.CurrentThread.Name)

                'Release the lock
                Interlocked.Exchange(usingResource, 0)
                Return True
            Else
                Console.WriteLine("   {0} was denied the lock", Thread.CurrentThread.Name)
                Return False
            End If
        End Function 
    End Class 
End Namespace

Remarques

Les méthodes de cette classe permettent de protéger contre les erreurs qui peuvent se produire lorsque le planificateur bascule des contextes pendant qu’un thread met à jour une variable accessible par d’autres threads ou lorsque deux threads s’exécutent simultanément sur des processeurs distincts. Les membres de cette classe ne lèvent pas d’exceptions.

Les Increment méthodes incrémentent Decrement ou décrémentent une variable et stockent la valeur résultante dans une seule opération. Sur la plupart des ordinateurs, l’incrémentation d’une variable n’est pas une opération atomique, nécessitant les étapes suivantes :

  1. Chargez une valeur à partir d’une variable d’instance dans un registre.

  2. Incrémenter ou décrémenter la valeur.

  3. Stockez la valeur dans la variable d’instance.

Si vous n’utilisez Increment pas et Decrementqu’un thread peut être préempté après avoir exécuté les deux premières étapes. Un autre thread peut ensuite exécuter les trois étapes. Lorsque le premier thread reprend l’exécution, il remplace la valeur dans la variable d’instance, et l’effet de l’incrément ou de la décrémentation effectuée par le deuxième thread est perdu.

La Add méthode ajoute atomiquement une valeur entière à une variable entière et retourne la nouvelle valeur de la variable.

La Exchange méthode échange de manière atomique les valeurs des variables spécifiées. La CompareExchange méthode combine deux opérations : comparer deux valeurs et stocker une troisième valeur dans l’une des variables, en fonction du résultat de la comparaison. Les opérations de comparaison et d’échange sont effectuées en tant qu’opération atomique.

Vérifiez que tout accès en écriture ou en lecture à une variable partagée est atomique. Sinon, les données peuvent être endommagées ou la valeur chargée peut être incorrecte.

Méthodes

Add(Int32, Int32)

Ajoute deux entiers à 32 bits et remplace le premier entier par la somme, sous la forme d'une opération atomique.

Add(Int64, Int64)

Ajoute deux entiers à 64 bits et remplace le premier entier par la somme, sous la forme d’une opération atomique.

Add(UInt32, UInt32)

Ajoute deux entiers 32 bits non signés et remplace le premier entier par la somme, sous la forme d’une opération atomique.

Add(UInt64, UInt64)

Ajoute deux entiers 64 bits non signés et remplace le premier entier par la somme, sous la forme d’une opération atomique.

And(Int32, Int32)

Effectue une opération AND au niveau du bit avec deux entiers 32 bits signés, et remplace le premier entier par le résultat, sous la forme d’une opération atomique.

And(Int64, Int64)

Effectue une opération AND au niveau du bit avec deux entiers 64 bits signés, et remplace le premier entier par le résultat, sous la forme d’une opération atomique.

And(UInt32, UInt32)

Effectue une opération AND au niveau du bit avec deux entiers 32 bits non signés, et remplace le premier entier par le résultat, sous la forme d’une opération atomique.

And(UInt64, UInt64)

Effectue une opération AND au niveau du bit avec deux entiers 64 bits non signés, et remplace le premier entier par le résultat, sous la forme d’une opération atomique.

CompareExchange(Double, Double, Double)

Compare deux nombres à virgule flottante double précision et remplace le premier en cas d'égalité.

CompareExchange(Int32, Int32, Int32)

Compare deux entiers signés de 32 bits et remplace la première valeur en cas d'égalité.

CompareExchange(Int64, Int64, Int64)

Compare deux entiers signés de 64 bits et remplace la première valeur en cas d'égalité.

CompareExchange(IntPtr, IntPtr, IntPtr)

Compare deux handles ou pointeurs spécifiques à la plateforme et remplace le premier en cas d’égalité.

CompareExchange(Object, Object, Object)

Compare deux objets et remplace le premier en cas d’égalité des références.

CompareExchange(Single, Single, Single)

Compare deux nombres à virgule flottante simple précision et remplace le premier en cas d'égalité.

CompareExchange(UInt32, UInt32, UInt32)

Compare deux entiers 32 bits non signés, et remplace la première valeur en cas d’égalité.

CompareExchange(UInt64, UInt64, UInt64)

Compare deux entiers 64 bits non signés, et remplace la première valeur en cas d’égalité.

CompareExchange(UIntPtr, UIntPtr, UIntPtr)

Compare deux handles ou pointeurs spécifiques à la plateforme et remplace le premier en cas d’égalité.

CompareExchange<T>(T, T, T)

Compare deux instances du type référence spécifié T pour et remplace la première en cas d’égalité par référence.

Decrement(Int32)

Décrémente une variable spécifiée et stocke le résultat, sous la forme d'une opération atomique.

Decrement(Int64)

Décrémente la variable spécifiée et stocke le résultat sous la forme d'une opération atomique.

Decrement(UInt32)

Décrémente une variable spécifiée et stocke le résultat, sous la forme d'une opération atomique.

Decrement(UInt64)

Décrémente une variable spécifiée et stocke le résultat, sous la forme d'une opération atomique.

Exchange(Double, Double)

Définit une valeur spécifiée pour un nombre à virgule flottante double précision, puis retourne la valeur d'origine, sous la forme d'une opération atomique.

Exchange(Int32, Int32)

Affecte un entier signé 32 bits à une valeur spécifiée, puis retourne la valeur d'origine, sous la forme d'une opération atomique.

Exchange(Int64, Int64)

Affecte un entier signé 64 bits à une valeur spécifiée, puis retourne la valeur d’origine, sous la forme d’une opération atomique.

Exchange(IntPtr, IntPtr)

Définit une valeur spécifiée pour un handle ou un pointeur spécifique à la plateforme, puis retourne la valeur d'origine, sous la forme d'une opération atomique.

Exchange(Object, Object)

Définit une valeur spécifiée pour un objet, puis retourne une référence à l'objet d'origine sous la forme d'une opération atomique.

Exchange(Single, Single)

Définit une valeur spécifiée pour un nombre à virgule flottante simple précision, puis retourne la valeur d'origine, sous la forme d'une opération atomique.

Exchange(UInt32, UInt32)

Affecte une valeur spécifiée à un entier 32 bits non signé, puis retourne la valeur d’origine sous la forme d’une opération atomique.

Exchange(UInt64, UInt64)

Affecte une valeur spécifiée à un entier 64 bits non signé, puis retourne la valeur d’origine sous la forme d’une opération atomique.

Exchange(UIntPtr, UIntPtr)

Définit une valeur spécifiée pour un handle ou un pointeur spécifique à la plateforme, puis retourne la valeur d'origine, sous la forme d'une opération atomique.

Exchange<T>(T, T)

Définit une valeur spécifiée pour une variable du type T spécifié et retourne la valeur d'origine, sous la forme d'une opération atomique.

Increment(Int32)

Incrémente une variable spécifiée et stocke le résultat sous la forme d'une opération atomique.

Increment(Int64)

Incrémente une variable spécifiée et stocke le résultat sous la forme d'une opération atomique.

Increment(UInt32)

Incrémente une variable spécifiée et stocke le résultat sous la forme d'une opération atomique.

Increment(UInt64)

Incrémente une variable spécifiée et stocke le résultat sous la forme d'une opération atomique.

MemoryBarrier()

Synchronise l'accès à la mémoire comme suit : le processeur qui exécute le thread actuel ne peut pas réorganiser les instructions de sorte que les accès à la mémoire avant l'appel de MemoryBarrier() s'exécutent après les accès à la mémoire postérieurs à l'appel de MemoryBarrier().

MemoryBarrierProcessWide()

Fournit un cloisonnement de mémoire à l’échelle du processus qui garantit que les lectures et les écritures des processeurs ne peuvent pas se déplacer au sein du cloisonnement.

Or(Int32, Int32)

Effectue une opération OR au niveau du bit avec deux entiers 32 bits signés, et remplace le premier entier par le résultat, sous la forme d’une opération atomique.

Or(Int64, Int64)

Effectue une opération OR au niveau du bit avec deux entiers 64 bits signés, et remplace le premier entier par le résultat, sous la forme d’une opération atomique.

Or(UInt32, UInt32)

Effectue une opération OR au niveau du bit avec deux entiers 32 bits non signés, et remplace le premier entier par le résultat, sous la forme d’une opération atomique.

Or(UInt64, UInt64)

Effectue une opération OR au niveau du bit avec deux entiers 64 bits non signés, et remplace le premier entier par le résultat, sous la forme d’une opération atomique.

Read(Int64)

Retourne une valeur de 64 bits chargée sous la forme d'une opération atomique.

Read(UInt64)

Retourne une valeur 64 bits non signée, chargée sous la forme d’une opération atomique.

SpeculationBarrier()

Définit une barrière de mémoire qui bloque l’exécution spéculative au-delà de ce point tant que les lectures et les écritures en attente ne sont pas terminées.

S’applique à

Cohérence de thread

Ce type est thread-safe.

Voir aussi