Sdílet prostřednictvím


Interlocked Třída

Definice

Poskytuje atomické operace pro proměnné, které jsou sdíleny více vlákny.

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
Dědičnost
Interlocked

Příklady

Následující příklad kódu ukazuje mechanismus uzamčení prostředků bezpečných vlákny.

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

Poznámky

Metody této třídy pomáhají chránit před chybami, ke kterým může dojít, když plánovač přepne kontexty v době, kdy vlákno aktualizuje proměnnou, ke které lze přistupovat jinými vlákny, nebo když jsou dvě vlákna spuštěna souběžně na samostatných procesorech. Členové této třídy nevyvolají výjimky.

Metody Increment a Decrement inkrementuje nebo dekrementuje proměnnou a uloží výslednou hodnotu do jedné operace. Ve většině počítačů není přírůstkem proměnné atomická operace, která vyžaduje následující kroky:

  1. Načtěte hodnotu z proměnné instance do registru.

  2. Zvýšení nebo snížení hodnoty

  3. Uložte hodnotu do proměnné instance.

Pokud nepoužíváte Increment a Decrement, po provedení prvních dvou kroků může být vlákno předem zrušeno. Další vlákno pak může provést všechny tři kroky. Když první vlákno obnoví provádění, přepíše hodnotu v proměnné instance a účinek přírůstku nebo dekrementu provedeného druhým vláknem se ztratí.

Metoda Add atomicky přidá celočíselnou hodnotu do celočíselné proměnné a vrátí novou hodnotu proměnné.

Metoda Exchange atomicky vyměňuje hodnoty zadaných proměnných. Metoda CompareExchange kombinuje dvě operace: porovnávání dvou hodnot a uložení třetí hodnoty do jedné z proměnných na základě výsledku porovnání. Operace porovnání a výměny se provádějí jako atomická operace.

Ujistěte se, že jakýkoli přístup pro zápis nebo čtení ke sdílené proměnné je atomický. V opačném případě mohou být data poškozena nebo načtená hodnota může být nesprávná.

Metody

Add(Int32, Int32)

Přidá dvě 32bitová celá čísla a nahradí první celé číslo součtem jako atomické operace.

Add(Int64, Int64)

Přidá dvě 64bitová celá čísla a nahradí první celé číslo součtem jako atomické operace.

Add(UInt32, UInt32)

Přidá dvě 32bitová celá čísla bez znaménka a nahradí první celé číslo součtem jako atomické operace.

Add(UInt64, UInt64)

Přidá dvě 64bitová celá čísla bez znaménka a nahradí první celé číslo součtem jako atomické operace.

And(Int32, Int32)

Bitové "ands" dvě 32bitová celá čísla a nahradí první celé číslo výsledkem atomické operace.

And(Int64, Int64)

Bitové "ands" dvě 64bitová celá čísla a nahradí první celé číslo výsledkem atomické operace.

And(UInt32, UInt32)

Bitové "ands" dvě 32bitová celá čísla bez znaménka a nahradí první celé číslo výsledkem jako atomická operace.

And(UInt64, UInt64)

Bitové "ands" dvě 64bitová celá čísla bez znaménka a nahradí první celé číslo výsledkem atomické operace.

CompareExchange(Byte, Byte, Byte)

Porovná dvě 8bitové celá čísla bez znaménka pro rovnost a pokud jsou stejné, nahradí první hodnotu.

CompareExchange(Double, Double, Double)

Porovná dvě čísla s plovoucí desetinnou čárkou s dvojitou přesností pro rovnost a pokud jsou stejná, nahradí první hodnotu.

CompareExchange(Int16, Int16, Int16)

Porovná dvě 16bitová celá čísla bez znaménka pro rovnost a pokud jsou rovny, nahradí první hodnotu.

CompareExchange(Int32, Int32, Int32)

Porovná dvě 32bitová celá čísla se dvěma signedem pro rovnost a pokud jsou rovna, nahradí první hodnotu.

CompareExchange(Int64, Int64, Int64)

Porovná dvě 64bitová celá čísla se signy pro rovnost a pokud jsou rovny, nahradí první hodnotu.

CompareExchange(IntPtr, IntPtr, IntPtr)

Porovná dva popisovače specifické pro platformu nebo ukazatele pro rovnost a pokud jsou stejné, nahradí první.

CompareExchange(Object, Object, Object)

Porovná dva objekty pro rovnost odkazů a pokud jsou stejné, nahradí první objekt.

CompareExchange(SByte, SByte, SByte)

Porovná dvě 8bitová celá čísla se dvěma signedem pro rovnost a pokud jsou rovna, nahradí první hodnotu.

CompareExchange(Single, Single, Single)

Porovná dvě čísla s plovoucí desetinnou čárkou s jednou přesností pro rovnost a pokud jsou stejná, nahradí první hodnotu.

CompareExchange(UInt16, UInt16, UInt16)

Porovná dvě 16bitová celá čísla se dvěma signedem pro rovnost a pokud jsou rovny, nahradí první hodnotu.

CompareExchange(UInt32, UInt32, UInt32)

Porovná dvě 32bitová celá čísla bez znaménka pro rovnost a pokud jsou stejné, nahradí první hodnotu.

CompareExchange(UInt64, UInt64, UInt64)

Porovná dvě 64bitová celá čísla bez znaménka pro rovnost a pokud jsou rovny, nahradí první hodnotu.

CompareExchange(UIntPtr, UIntPtr, UIntPtr)

Porovná dva popisovače specifické pro platformu nebo ukazatele pro rovnost a pokud jsou stejné, nahradí první.

CompareExchange<T>(T, T, T)

Porovná dvě instance zadaného typu odkazu T rovnosti odkazů a pokud jsou stejné, nahradí první.

Decrement(Int32)

Dekrementuje zadanou proměnnou a uloží výsledek jako atomická operace.

Decrement(Int64)

Sníží zadanou proměnnou a uloží výsledek jako atomické operace.

Decrement(UInt32)

Dekrementuje zadanou proměnnou a uloží výsledek jako atomická operace.

Decrement(UInt64)

Dekrementuje zadanou proměnnou a uloží výsledek jako atomická operace.

Exchange(Byte, Byte)

Nastaví 8bitové celé číslo bez znaménka na zadanou hodnotu a vrátí původní hodnotu jako atomické operace.

Exchange(Double, Double)

Nastaví číslo s plovoucí desetinnou čárkou s dvojitou přesností na zadanou hodnotu a vrátí původní hodnotu jako atomické operace.

Exchange(Int16, Int16)

Nastaví 16bitové celé číslo bez znaménka na zadanou hodnotu a vrátí původní hodnotu jako atomické operace.

Exchange(Int32, Int32)

Nastaví 32bitové celé číslo podepsané na zadanou hodnotu a vrátí původní hodnotu jako atomické operace.

Exchange(Int64, Int64)

Nastaví 64bitové celé číslo se signedem na zadanou hodnotu a vrátí původní hodnotu jako atomické operace.

Exchange(IntPtr, IntPtr)

Nastaví popisovač specifický pro platformu nebo ukazatel na zadanou hodnotu a vrátí původní hodnotu jako atomické operace.

Exchange(Object, Object)

Nastaví objekt na zadanou hodnotu a vrátí odkaz na původní objekt jako atomické operace.

Exchange(SByte, SByte)

Nastaví 8bitové celé číslo podepsané na zadanou hodnotu a vrátí původní hodnotu jako atomické operace.

Exchange(Single, Single)

Nastaví číslo s plovoucí desetinnou čárkou s jednoduchou přesností na zadanou hodnotu a vrátí původní hodnotu jako atomické operace.

Exchange(UInt16, UInt16)

Nastaví 16bitové celé číslo se signedem na zadanou hodnotu a vrátí původní hodnotu jako atomické operace.

Exchange(UInt32, UInt32)

Nastaví 32bitové celé číslo bez znaménka na zadanou hodnotu a vrátí původní hodnotu jako atomickou operaci.

Exchange(UInt64, UInt64)

Nastaví 64bitové celé číslo bez znaménka na zadanou hodnotu a vrátí původní hodnotu jako atomické operace.

Exchange(UIntPtr, UIntPtr)

Nastaví popisovač specifický pro platformu nebo ukazatel na zadanou hodnotu a vrátí původní hodnotu jako atomické operace.

Exchange<T>(T, T)

Nastaví proměnnou zadaného typu T na zadanou hodnotu a vrátí původní hodnotu jako atomické operace.

Increment(Int32)

Zvýší zadanou proměnnou a uloží výsledek jako atomická operace.

Increment(Int64)

Zvýší zadanou proměnnou a uloží výsledek jako atomická operace.

Increment(UInt32)

Zvýší zadanou proměnnou a uloží výsledek jako atomická operace.

Increment(UInt64)

Zvýší zadanou proměnnou a uloží výsledek jako atomická operace.

MemoryBarrier()

Synchronizuje přístup k paměti následujícím způsobem: Procesor, který spouští aktuální vlákno, nemůže změnit pořadí instrukcí tak, aby paměť přistupovala před voláním MemoryBarrier() spustit po přístupu k paměti, které následují za voláním MemoryBarrier().

MemoryBarrierProcessWide()

Poskytuje bariéru paměti pro celý proces, která zajišťuje, že čtení a zápisy z jakéhokoli procesoru se nemůže pohybovat přes bariéru.

Or(Int32, Int32)

Bitové "ors" dvě 32bitová celá čísla a nahradí první celé číslo výsledkem atomické operace.

Or(Int64, Int64)

Bitové "ors" dvě 64bitové signed integers a nahradí první celé číslo výsledkem, jako atomické operace.

Or(UInt32, UInt32)

Bitové "ors" dvě 32bitová celá čísla bez znaménka a nahradí první celé číslo výsledkem jako atomická operace.

Or(UInt64, UInt64)

Bitové "ors" dvě 64bitová celá čísla bez znaménka a nahradí první celé číslo výsledkem jako atomická operace.

Read(Int64)

Vrátí 64bitovou hodnotu načtenou jako atomická operace.

Read(UInt64)

Vrátí 64bitovou hodnotu bez znaménka načtenou jako atomická operace.

SpeculationBarrier()

Definuje plot paměti, který blokuje spekulativní spuštění až do dokončení čekajících čtení a zápisů.

Platí pro

Bezpečný přístup z více vláken

Tento typ je bezpečný pro přístup z více vláken.

Viz také