Interlocked Clase

Definición

Proporciona operaciones atómicas para las variables compartidas por varios subprocesos.

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
Herencia
Interlocked

Ejemplos

En el ejemplo de código siguiente se muestra un mecanismo de bloqueo de recursos seguro para subprocesos.

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

Comentarios

Los métodos de esta clase ayudan a protegerse frente a errores que pueden producirse cuando el programador cambia los contextos mientras un subproceso actualiza una variable a la que pueden acceder otros subprocesos o cuando se ejecutan dos subprocesos simultáneamente en procesadores independientes. Los miembros de esta clase no inician excepciones.

Los Increment métodos y Decrement incrementan o reducen una variable y almacenan el valor resultante en una sola operación. En la mayoría de los equipos, incrementar una variable no es una operación atómica, lo que requiere los pasos siguientes:

  1. Cargue un valor de una variable de instancia en un registro.

  2. Incremente o disminuya el valor.

  3. Almacene el valor en la variable de instancia.

Si no usa Increment y Decrement, se puede adelantar un subproceso después de ejecutar los dos primeros pasos. Después, otro subproceso puede ejecutar los tres pasos. Cuando el primer subproceso reanuda la ejecución, sobrescribe el valor de la variable de instancia y se pierde el efecto del incremento o disminución realizado por el segundo subproceso.

El Add método agrega de forma atómica un valor entero a una variable de entero y devuelve el nuevo valor de la variable.

El Exchange método intercambia de forma atómica los valores de las variables especificadas. El CompareExchange método combina dos operaciones: comparando dos valores y almacenando un tercer valor en una de las variables, en función del resultado de la comparación. Las operaciones de comparación e intercambio se realizan como una operación atómica.

Asegúrese de que cualquier acceso de escritura o lectura a una variable compartida sea atómica. De lo contrario, los datos podrían estar dañados o el valor cargado podría ser incorrecto.

Métodos

Add(Int32, Int32)

Agrega dos enteros de 32 bits y reemplaza el primer entero por la suma, como una operación atómica.

Add(Int64, Int64)

Agrega dos enteros de 64 bits y reemplaza el primer entero por la suma, como operación atómica.

Add(UInt32, UInt32)

Agrega dos enteros sin signo de 32 bits y reemplaza el primer entero por la suma, como una operación atómica.

Add(UInt64, UInt64)

Agrega dos enteros sin signo de 64 bits y reemplaza el primer entero por la suma, como una operación atómica.

And(Int32, Int32)

Dos enteros con signo de 32  bits de bit "and" y reemplaza el primer entero por el resultado, como una operación atómica.

And(Int64, Int64)

Dos enteros con signo de 64 bits de bit "and" y reemplaza el primer entero por el resultado, como una operación atómica.

And(UInt32, UInt32)

Dos enteros sin signo de 32 bits "and" y reemplaza el primer entero por el resultado, como una operación atómica.

And(UInt64, UInt64)

Dos enteros sin signo de 64 bits "and" y reemplaza el primer entero por el resultado, como una operación atómica.

CompareExchange(Double, Double, Double)

Compara dos números de punto flotante de precisión doble para comprobar si son iguales y, si lo son, reemplaza el primero de los valores.

CompareExchange(Int32, Int32, Int32)

Compara dos enteros de 32 bits con signo para comprobar si son iguales y, si lo son, reemplaza el primer valor.

CompareExchange(Int64, Int64, Int64)

Compara dos enteros de 64 bits con signo para comprobar si son iguales y, si lo son, reemplaza el primer valor.

CompareExchange(IntPtr, IntPtr, IntPtr)

Compara dos identificadores o punteros específicos de la plataforma en términos de igualdad y, si son iguales, reemplaza el primero.

CompareExchange(Object, Object, Object)

Compara dos objetos en términos de igualdad de referencia y, si son iguales, reemplaza el primero.

CompareExchange(Single, Single, Single)

Compara dos números de punto flotante de precisión sencilla para comprobar si son iguales y, si lo son, reemplaza el primero de los valores.

CompareExchange(UInt32, UInt32, UInt32)

Compara los dos enteros sin signo de 32 bits para determinar si son iguales y, si lo son, reemplaza el primer valor.

CompareExchange(UInt64, UInt64, UInt64)

Compara los dos enteros sin signo de 64 bits para determinar si son iguales y, si lo son, reemplaza el primer valor.

CompareExchange(UIntPtr, UIntPtr, UIntPtr)

Compara dos identificadores o punteros específicos de la plataforma en términos de igualdad y, si son iguales, reemplaza el primero.

CompareExchange<T>(T, T, T)

Compara dos instancias del tipo de referencia especificado T para comprobar si las referencias son iguales y, si lo son, reemplaza la primera.

Decrement(Int32)

Disminuye el valor de una variable especificada y almacena el resultado, como una operación atómica.

Decrement(Int64)

Disminuye el valor de la variable especificada y almacena el resultado, como una operación atómica.

Decrement(UInt32)

Disminuye el valor de una variable especificada y almacena el resultado, como una operación atómica.

Decrement(UInt64)

Disminuye el valor de una variable especificada y almacena el resultado, como una operación atómica.

Exchange(Double, Double)

Establece un número de punto flotante de precisión doble en un valor especificado y devuelve el valor original, como una operación atómica.

Exchange(Int32, Int32)

Establece un entero de 32 bits con signo en un valor especificado y devuelve el valor original, como una operación atómica.

Exchange(Int64, Int64)

Establece un entero de 64 bits con signo en un valor especificado y devuelve el valor original, como operación atómica.

Exchange(IntPtr, IntPtr)

Establece un puntero o identificador específico de plataforma en un valor especificado y devuelve el valor original, como una operación atómica.

Exchange(Object, Object)

Establece un objeto en un valor especificado y devuelve una referencia al objeto original, como una operación atómica.

Exchange(Single, Single)

Establece un número de punto flotante de precisión sencilla en un valor especificado y devuelve el valor original, como una operación atómica.

Exchange(UInt32, UInt32)

Establece un entero sin signo de 32 bits en un valor especificado y devuelve el valor original, como una operación atómica.

Exchange(UInt64, UInt64)

Establece un entero sin signo de 64 bits en un valor especificado y devuelve el valor original, como una operación atómica.

Exchange(UIntPtr, UIntPtr)

Establece un puntero o identificador específico de plataforma en un valor especificado y devuelve el valor original, como una operación atómica.

Exchange<T>(T, T)

Establece una variable del tipo T especificado en un valor determinado y devuelve el valor original, como una operación atómica.

Increment(Int32)

Aumenta el valor de una variable especificada y almacena el resultado, como una operación atómica.

Increment(Int64)

Aumenta el valor de una variable especificada y almacena el resultado, como una operación atómica.

Increment(UInt32)

Aumenta el valor de una variable especificada y almacena el resultado, como una operación atómica.

Increment(UInt64)

Aumenta el valor de una variable especificada y almacena el resultado, como una operación atómica.

MemoryBarrier()

Sincroniza el acceso a la memoria de la siguiente forma: el procesador que ejecuta el subproceso actual no puede reordenar instrucciones de forma que los accesos a la memoria anteriores a la llamada a MemoryBarrier() se ejecuten después de los accesos a memoria que siguen a la llamada a MemoryBarrier().

MemoryBarrierProcessWide()

Proporciona una barrera de memoria para todo el proceso con el fin de asegurar que las operaciones de lectura y escritura desde cualquier CPU no puedan superar la barrera.

Or(Int32, Int32)

Dos enteros con signo de 32 bits de bit "ors" y reemplaza el primer entero por el resultado, como una operación atómica.

Or(Int64, Int64)

Dos enteros con signo de 64 bits de bit "ors" y reemplaza el primer entero por el resultado, como una operación atómica.

Or(UInt32, UInt32)

Dos enteros sin signo de 32 bits "ors" y reemplaza el primer entero por el resultado, como una operación atómica.

Or(UInt64, UInt64)

Dos enteros sin signo de 64 bits "ors" y reemplaza el primer entero por el resultado, como una operación atómica.

Read(Int64)

Devuelve un valor de 64 bits, cargado como una operación atómica.

Read(UInt64)

Devuelve un valor sin signo de 64 bits, cargado como una operación atómica.

SpeculationBarrier()

Define una barrera de memoria que bloquea la ejecución especulativa después de este punto hasta que se complementen las lecturas y escrituras pendientes.

Se aplica a

Seguridad para subprocesos

Este tipo es seguro para la ejecución de subprocesos.

Consulte también