Interlocked Classe

Definizione

Consente di eseguire operazioni atomiche per variabili condivise da più thread.

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
Ereditarietà
Interlocked

Esempio

L'esempio di codice seguente illustra un meccanismo di blocco delle risorse 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

Commenti

I metodi di questa classe consentono di proteggere da errori che possono verificarsi quando l'utilità di pianificazione cambia i contesti mentre un thread aggiorna una variabile a cui è possibile accedere da altri thread o quando due thread vengono eseguiti simultaneamente in processori separati. I membri di questa classe non generano eccezioni.

I Increment metodi e Decrement incrementino o decrementano una variabile e archiviano il valore risultante in una singola operazione. Nella maggior parte dei computer, l'incremento di una variabile non è un'operazione atomica, che richiede i passaggi seguenti:

  1. Caricare un valore da una variabile di istanza in un registro.

  2. Incrementare o decrementare il valore.

  3. Archiviare il valore nella variabile di istanza.

Se non si usa Increment e Decrement, un thread può essere preceduto dall'esecuzione dei primi due passaggi. Un altro thread può quindi eseguire tutti e tre i passaggi. Quando il primo thread riprende l'esecuzione, sovrascrive il valore nella variabile di istanza e l'effetto dell'incremento o del decremento eseguito dal secondo thread viene perso.

Il Add metodo aggiunge in modo atomico un valore integer a una variabile integer e restituisce il nuovo valore della variabile.

Il Exchange metodo scambia in modo atomico i valori delle variabili specificate. Il CompareExchange metodo combina due operazioni: confrontando due valori e archiviando un terzo valore in una delle variabili, in base al risultato del confronto. Le operazioni di confronto e scambio vengono eseguite come operazione atomica.

Assicurarsi che qualsiasi accesso in scrittura o lettura a una variabile condivisa sia atomico. In caso contrario, i dati potrebbero essere danneggiati o il valore caricato potrebbe non essere corretto.

Metodi

Add(Int32, Int32)

Aggiunge due Integer a 32 bit e sostituisce il primo con la somma, come operazione atomica.

Add(Int64, Int64)

Aggiunge due Integer a 64 bit e sostituisce il primo con la somma, come operazione atomica.

Add(UInt32, UInt32)

Somma due interi senza segno a 32 bit e sostituisce il primo intero con la somma, come operazione atomica.

Add(UInt64, UInt64)

Somma due interi senza segno a 64 bit e sostituisce il primo intero con la somma, come operazione atomica.

And(Int32, Int32)

Viene eseguita l'operazione AND bit per bit di due interi con segno a 32 bit e viene sostituito il primo intero con il risultato, come operazione atomica.

And(Int64, Int64)

Viene eseguita l'operazione AND bit per bit di due interi con segno a 64 bit e viene sostituito il primo intero con il risultato, come operazione atomica.

And(UInt32, UInt32)

Viene eseguita l'operazione AND bit per bit di due interi senza segno a 32 bit e viene sostituito il primo intero con il risultato, come operazione atomica.

And(UInt64, UInt64)

Viene eseguita l'operazione AND bit per bit di due interi senza segno a 64 bit e viene sostituito il primo intero con il risultato, come operazione atomica.

CompareExchange(Double, Double, Double)

Confronta due numeri a virgola mobile e precisione doppia per verificarne l'uguaglianza; se sono uguali, sostituisce il primo valore.

CompareExchange(Int32, Int32, Int32)

Confronta due interi con segno a 32 bit per verificarne l'uguaglianza; se sono uguali, sostituisce il primo valore.

CompareExchange(Int64, Int64, Int64)

Confronta due interi con segno a 64 bit per verificarne l'uguaglianza; se sono uguali, sostituisce il primo valore.

CompareExchange(IntPtr, IntPtr, IntPtr)

Confronta due puntatori o handle specifici della piattaforma per verificarne l'uguaglianza. Se sono uguali, sostituisce il primo elemento.

CompareExchange(Object, Object, Object)

Confronta due oggetti per verificarne l'uguaglianza dei riferimenti. Se sono uguali, sostituisce il primo oggetto.

CompareExchange(Single, Single, Single)

Confronta due numeri a virgola mobile e precisione singola per verificarne l'uguaglianza; se sono uguali, sostituisce il primo valore.

CompareExchange(UInt32, UInt32, UInt32)

Confronta due interi senza segno a 32 bit per verificarne l'uguaglianza; se sono uguali, sostituisce il primo valore.

CompareExchange(UInt64, UInt64, UInt64)

Confronta due interi senza segno a 64 bit per verificarne l'uguaglianza; se sono uguali, sostituisce il primo valore.

CompareExchange(UIntPtr, UIntPtr, UIntPtr)

Confronta due puntatori o handle specifici della piattaforma per verificarne l'uguaglianza. Se sono uguali, sostituisce il primo elemento.

CompareExchange<T>(T, T, T)

Confronta due istanze del tipo di riferimento T specificato per verificarne l'uguaglianza dei riferimenti. Se sono uguali, sostituisce la prima istanza.

Decrement(Int32)

Consente di diminuire una variabile specificata e di memorizzarne il risultato, come operazione atomica.

Decrement(Int64)

Consente di diminuire la variabile specificata e di memorizzare il risultato, come operazione atomica.

Decrement(UInt32)

Consente di diminuire una variabile specificata e di memorizzarne il risultato, come operazione atomica.

Decrement(UInt64)

Consente di diminuire una variabile specificata e di memorizzarne il risultato, come operazione atomica.

Exchange(Double, Double)

Imposta un numero in virgola mobile a precisione doppia su un valore specificato e restituisce il valore originale, come operazione atomica.

Exchange(Int32, Int32)

Imposta un intero con segno a 32 bit su un valore specificato e restituisce il valore originale, come operazione atomica.

Exchange(Int64, Int64)

Imposta un intero con segno a 64 bit su un valore specificato e restituisce il valore originale, come operazione atomica.

Exchange(IntPtr, IntPtr)

Imposta un puntatore o un handle specifico della piattaforma su un valore specificato e restituisce il valore originale, come operazione atomica.

Exchange(Object, Object)

Imposta un oggetto su un valore specificato e restituisce un riferimento all'oggetto originale, come operazione atomica.

Exchange(Single, Single)

Imposta un numero in virgola mobile a precisione singola su un valore specificato e restituisce il valore originale, come operazione atomica.

Exchange(UInt32, UInt32)

Imposta un intero senza segno a 32 bit su un valore specificato e restituisce il valore originale, come operazione atomica.

Exchange(UInt64, UInt64)

Imposta un intero senza segno a 64 bit su un valore specificato e restituisce il valore originale, come operazione atomica.

Exchange(UIntPtr, UIntPtr)

Imposta un puntatore o un handle specifico della piattaforma su un valore specificato e restituisce il valore originale, come operazione atomica.

Exchange<T>(T, T)

Imposta una variabile del tipo T indicato sul valore specificato e restituisce il valore originale, come operazione atomica.

Increment(Int32)

Aumenta una variabile specificata e archivia il risultato, come operazione atomica.

Increment(Int64)

Aumenta una variabile specificata e archivia il risultato, come operazione atomica.

Increment(UInt32)

Aumenta una variabile specificata e archivia il risultato, come operazione atomica.

Increment(UInt64)

Aumenta una variabile specificata e archivia il risultato, come operazione atomica.

MemoryBarrier()

Sincronizza l'accesso della memoria nel modo descritto di seguito. Il processore che esegue il thread corrente non può riordinare istruzioni in modo che gli accessi alla memoria prima della chiamata al metodo MemoryBarrier() vengano eseguiti dopo quelli successivi alla chiamata al metodo MemoryBarrier().

MemoryBarrierProcessWide()

Offre una barriera di memoria estesa ai processi che assicura che le letture e le scritture da qualsiasi CPU non possano superare la barriera.

Or(Int32, Int32)

Viene eseguita l'operazione OR bit per bit di due interi con segno a 32 bit e viene sostituito il primo intero con il risultato, come operazione atomica.

Or(Int64, Int64)

Viene eseguita l'operazione OR bit per bit di due interi con segno a 64 bit e viene sostituito il primo intero con il risultato, come operazione atomica.

Or(UInt32, UInt32)

Viene eseguita l'operazione OR bit per bit di due interi senza segno a 32 bit e viene sostituito il primo intero con il risultato, come operazione atomica.

Or(UInt64, UInt64)

Viene eseguita l'operazione OR bit per bit di due interi senza segno a 64 bit e viene sostituito il primo intero con il risultato, come operazione atomica.

Read(Int64)

Restituisce un valore a 64 bit, caricato come operazione atomica.

Read(UInt64)

Restituisce un valore senza segno a 64 bit, caricato come operazione atomica.

SpeculationBarrier()

Definisce un limite di memoria che blocca l'esecuzione speculativa oltre questo punto fino al completamento delle letture e scritture in sospeso.

Si applica a

Thread safety

Questo tipo è thread-safe.

Vedi anche