Compartir vía


Interlocked Clase

Definición

Proporciona operaciones atómicas para 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 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 métodos Increment y Decrement incrementan o reducen una variable y almacenan el valor resultante en una sola operación. En la mayoría de los equipos, el incremento de 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. A continuación, otro subproceso puede ejecutar los tres pasos. Cuando el primer subproceso reanuda la ejecución, sobrescribe el valor en la variable de instancia y se pierde el efecto del incremento o disminución realizado por el segundo subproceso.

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

El método Exchange intercambia atómicamente los valores de las variables especificadas. El método CompareExchange 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, es posible que los datos estén dañados o que el valor cargado sea 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 una operación atómica.

Add(UInt32, UInt32)

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

Add(UInt64, UInt64)

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

And(Int32, Int32)

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

And(Int64, Int64)

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

And(UInt32, UInt32)

"ands" bit a bit dos enteros sin signo de 32 bits y reemplaza el primer entero por el resultado, como una operación atómica.

And(UInt64, UInt64)

"ands" bit a bit dos enteros sin signo de 64 bits y reemplaza el primer entero por el resultado, como una operación atómica.

CompareExchange(Byte, Byte, Byte)

Compara dos enteros sin signo de 8 bits para la igualdad y, si son iguales, reemplaza el primer valor, como una operación atómica.

CompareExchange(Double, Double, Double)

Compara dos números de punto flotante de doble precisión para la igualdad y, si son iguales, reemplaza el primer valor, como una operación atómica.

CompareExchange(Int16, Int16, Int16)

Compara dos enteros sin signo de 16 bits para obtener igualdad y, si son iguales, reemplaza el primer valor, como una operación atómica.

CompareExchange(Int32, Int32, Int32)

Compara dos enteros de 32 bits con signo para obtener igualdad y, si son iguales, reemplaza el primer valor, como una operación atómica.

CompareExchange(Int64, Int64, Int64)

Compara dos enteros de 64 bits con signo para obtener igualdad y, si son iguales, reemplaza el primer valor, como una operación atómica.

CompareExchange(IntPtr, IntPtr, IntPtr)

Compara dos identificadores o punteros específicos de la plataforma para la igualdad y, si son iguales, reemplaza el primero, como una operación atómica.

CompareExchange(Object, Object, Object)

Compara dos objetos para la igualdad de referencia y, si son iguales, reemplaza el primer objeto, como una operación atómica.

CompareExchange(SByte, SByte, SByte)

Compara dos enteros con signo de 8 bits para obtener igualdad y, si son iguales, reemplaza el primer valor, como una operación atómica.

CompareExchange(Single, Single, Single)

Compara dos números de punto flotante de precisión única para la igualdad y, si son iguales, reemplaza el primer valor, como una operación atómica.

CompareExchange(UInt16, UInt16, UInt16)

Compara dos enteros de 16 bits con signo para obtener igualdad y, si son iguales, reemplaza el primer valor, como una operación atómica.

CompareExchange(UInt32, UInt32, UInt32)

Compara dos enteros de 32 bits sin signo para obtener igualdad y, si son iguales, reemplaza el primer valor, como una operación atómica.

CompareExchange(UInt64, UInt64, UInt64)

Compara dos enteros de 64 bits sin signo para la igualdad y, si son iguales, reemplaza el primer valor, como una operación atómica.

CompareExchange(UIntPtr, UIntPtr, UIntPtr)

Compara dos identificadores o punteros específicos de la plataforma para la igualdad y, si son iguales, reemplaza el primero, como una operación atómica.

CompareExchange<T>(T, T, T)

Compara dos instancias del tipo de referencia especificado T para la igualdad de referencia y, si son iguales, reemplaza la primera, como una operación atómica.

Decrement(Int32)

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

Decrement(Int64)

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

Decrement(UInt32)

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

Decrement(UInt64)

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

Exchange(Byte, Byte)

Establece un entero de 8 bits sin signo en un valor especificado y devuelve el valor original, 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(Int16, Int16)

Establece un entero de 16 bits sin signo 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 una operación atómica.

Exchange(IntPtr, IntPtr)

Establece un identificador o puntero específico de la 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(SByte, SByte)

Establece un entero de 8 bits con signo en un valor especificado y devuelve el valor 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(UInt16, UInt16)

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

Exchange(UInt32, UInt32)

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

Exchange(UInt64, UInt64)

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

Exchange(UIntPtr, UIntPtr)

Establece un identificador o puntero específico de la 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 especificado T en un valor especificado y devuelve el valor original, como una operación atómica.

Increment(Int32)

Incrementa una variable especificada y almacena el resultado, como una operación atómica.

Increment(Int64)

Incrementa una variable especificada y almacena el resultado, como una operación atómica.

Increment(UInt32)

Incrementa una variable especificada y almacena el resultado, como una operación atómica.

Increment(UInt64)

Incrementa una variable especificada y almacena el resultado, como una operación atómica.

MemoryBarrier()

Sincroniza el acceso a la memoria de la siguiente manera: el procesador que ejecuta el subproceso actual no puede reordenar las instrucciones de forma que la memoria tenga acceso antes de que la llamada a MemoryBarrier() ejecute después de los accesos de memoria que siguen la llamada a MemoryBarrier().

MemoryBarrierProcessWide()

Proporciona una barrera de memoria para todo el proceso que garantiza que las lecturas y escrituras de cualquier CPU no se puedan mover a través de la barrera.

Or(Int32, Int32)

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

Or(Int64, Int64)

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

Or(UInt32, UInt32)

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

Or(UInt64, UInt64)

"ors" bit a bit dos enteros sin signo de 64 bits 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 más allá de este punto hasta que se completen las lecturas y escrituras pendientes.

Se aplica a

Seguridad para subprocesos

Este tipo es seguro para subprocesos.

Consulte también