Interlocked Osztály

Definíció

Atomi műveleteket biztosít több szál által megosztott változókhoz.

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
Öröklődés
Interlocked

Példák

Az alábbi példakód egy szálbiztos erőforrás-zárolási mechanizmust mutat be.

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

Megjegyzések

Az osztály módszerei segítenek védelmet nyújtani azokkal a hibákkal szemben, amelyek akkor fordulhatnak elő, amikor az ütemező környezeteket vált, miközben egy szál olyan változót frissít, amelyet más szálak érhetnek el, vagy ha két szál egyidejűleg fut külön processzorokon. Az osztály tagjai nem adnak kivételeket.

A Increment változók és Decrement metódusok növekménye vagy csökkentése, valamint az eredményként kapott érték tárolása egyetlen műveletben. A legtöbb számítógépen a változók növekménye nem atomi művelet, amely a következő lépéseket igényli:

  1. Egy példányváltozóból származó érték betöltése egy regiszterbe.
  2. Az érték növelése vagy csökkentése.
  3. Tárolja az értéket a példányváltozóban.

Ha nem használja Increment , és Decrementaz első két lépés végrehajtása után egy szál elővehető. Ezután egy másik szál mindhárom lépést végrehajthatja. Amikor az első szál folytatja a végrehajtást, felülírja a példányváltozó értékét, és a második szál által végrehajtott növekmény vagy csökkenés hatása elveszik.

A Add metódus atomilag hozzáad egy egész számot egy egész szám változóhoz, és visszaadja a változó új értékét.

A Exchange metódus atomilag kicseréli a megadott változók értékeit. A CompareExchange módszer két műveletet kombinál: két érték összehasonlítását és egy harmadik érték tárolását az egyik változóban az összehasonlítás eredménye alapján. Az összehasonlítási és csereműveleteket atomi műveletként hajtjuk végre.

Győződjön meg arról, hogy a megosztott változók írási vagy olvasási hozzáférése atomi. Ellenkező esetben előfordulhat, hogy az adatok sérültek, vagy a betöltött érték helytelen.

Metódusok

Name Description
Add(Int32, Int32)

Két 32 bites egész számot ad hozzá, és az első egész számot az összegre cseréli atomi műveletként.

Add(Int64, Int64)

Két 64 bites egész számot ad hozzá, és az első egész számot az összegre cseréli atomi műveletként.

CompareExchange(Double, Double, Double)

Az egyenlőség két dupla pontosságú lebegőpontos számát hasonlítja össze, és ha egyenlőek, az első értéket atomi műveletként cseréli le.

CompareExchange(Int32, Int32, Int32)

Összehasonlít két 32 bites aláírt egész számot az egyenlőséghez, és ha egyenlőek, az első értéket atomi műveletként cseréli le.

CompareExchange(Int64, Int64, Int64)

Összehasonlít két 64 bites aláírt egész számot az egyenlőséghez, és ha egyenlőek, az első értéket atomi műveletként cseréli le.

CompareExchange(IntPtr, IntPtr, IntPtr)

Összehasonlít két natív méretű aláírt egész számot az egyenlőség érdekében, és ha egyenlőek, az elsőt atomi műveletként helyettesíti.

CompareExchange(Object, Object, Object)

Összehasonlít két objektumot a referenciaegyenlőség szempontjából, és ha egyenlőek, az első objektumot atomi műveletként helyettesíti.

CompareExchange(Single, Single, Single)

Az egyenlőség két egypontos lebegőpontos számát hasonlítja össze, és ha egyenlőek, az első értéket atomi műveletként cseréli le.

CompareExchange<T>(T, T, T)

Összehasonlítja a hivatkozási egyenlőség megadott típusának T két példányát, és ha egyenlőek, az elsőt atomi műveletként cseréli le.

Decrement(Int32)

Egy megadott változót dekreál, és az eredményt atomi műveletként tárolja.

Decrement(Int64)

A megadott változót dekreálja, és az eredményt atomi műveletként tárolja.

Exchange(Double, Double)

Dupla pontosságú lebegőpontos számot állít be egy megadott értékre, és az eredeti értéket adja vissza atomi műveletként.

Exchange(Int32, Int32)

32 bites aláírt egész számot állít be egy megadott értékre, és az eredeti értéket adja vissza atomi műveletként.

Exchange(Int64, Int64)

Egy 64 bites aláírt egész számot állít be egy megadott értékre, és az eredeti értéket adja vissza atomi műveletként.

Exchange(IntPtr, IntPtr)

Natív méretű aláírt egész számot állít be egy megadott értékre, és az eredeti értéket adja vissza atomi műveletként.

Exchange(Object, Object)

Egy objektumot egy megadott értékre állít be, és az eredeti objektumra mutató hivatkozást ad vissza atomi műveletként.

Exchange(Single, Single)

Egy egypontos lebegőpontos számot állít be egy megadott értékre, és az eredeti értéket adja vissza atomi műveletként.

Exchange<T>(T, T)

A megadott típusú T változót egy megadott értékre állítja be, és az eredeti értéket adja vissza atomi műveletként.

Increment(Int32)

Egy megadott változót növekményesen tárol, és atomi műveletként tárolja az eredményt.

Increment(Int64)

Egy megadott változót növekményesen tárol, és atomi műveletként tárolja az eredményt.

MemoryBarrier()

A következő módon szinkronizálja a memóriahozzáférést: Az aktuális szálat végrehajtó processzor nem tudja úgy átrendezni az utasításokat, hogy a memória a hívás előtt hozzáférhessen MemoryBarrier() a híváshoz, miután a hívást követő memóriahozzáférések következnek MemoryBarrier().

MemoryBarrierProcessWide()

Egy folyamatszintű memóriakorlátot biztosít, amely biztosítja, hogy az olvasási és írási műveletek nem haladhatók át az akadályon.

Read(Int64)

Egy 64 bites értéket ad vissza, amely atomi műveletként van betöltve.

SpeculationBarrier()

Definiál egy memóriakerítést, amely blokkolja a spekulatív végrehajtást ezen a ponton, amíg a függőben lévő olvasások és írások befejeződnek.

A következőre érvényes:

Szálbiztonság

Ez a típus szálbiztos.

Lásd még