SyncLock utasítás

A blokk végrehajtása előtt kizárólagos zárolást szerez be egy utasításblokkhoz.

Syntax

SyncLock lockobject  
    [ block ]  
End SyncLock  

Részek

lockobject
Szükséges. Objektumhivatkozásként kiértékelt kifejezés.

block
Opcionális. A zárolás beszerzésekor végrehajtandó utasítások blokkja.

End SyncLock
Leállítja a blokkot SyncLock .

Megjegyzések

Az SyncLock utasítás biztosítja, hogy több szál ne hajtsa végre egyszerre az utasításblokkot. SyncLock megakadályozza, hogy az egyes szálak mindaddig belépnek a blokkba, amíg más szál nem hajtja végre.

A leggyakoribb használat SyncLock az adatok több szál általi egyidejű frissítésének védelme. Ha az adatokat kezelő utasításoknak megszakítás nélkül kell befejeződniük, helyezze őket egy SyncLock blokkba.

A kizárólagos zárolással védett utasításblokkokat kritikus szakasznak is nevezik.

Szabályok

  • Elágazó. A blokkon kívülről nem ágazhat be blokkba SyncLock .

  • Objektumérték zárolása. Az érték lockobject nem lehet Nothing. A zárolási objektumot az utasításban SyncLock való használat előtt létre kell hoznia.

    A blokk végrehajtása közben nem módosíthatja lockobject az értékeket SyncLock . A mechanizmus megköveteli, hogy a zárolási objektum változatlan maradjon.

  • Blokkban nem használhatja a Várakozás operátort SyncLock .

Működés

  • Mechanizmus. Amikor egy szál eléri az SyncLock utasítást, kiértékeli a kifejezést, és felfüggeszti a lockobject végrehajtást, amíg nem szerez kizárólagos zárolást a kifejezés által visszaadott objektumon. Amikor egy másik szál eléri az SyncLock utasítást, nem szerez be zárolást, amíg az első szál nem hajtja végre az utasítást End SyncLock .

  • Védett adatok. Ha lockobject változó Shared , a kizárólagos zárolás megakadályozza, hogy az osztály bármely példányában egy szál végrehajtsa a SyncLock blokkot, miközben bármely más szál végrehajtja azt. Ez védi az összes példány között megosztott adatokat.

    Ha lockobject egy példányváltozó (nem Shared), a zárolás megakadályozza, hogy az aktuális példányban futó szál a blokkot ugyanabban a SyncLock példányban egy másik szállal egyidejűleg hajtsa végre. Ez védi az egyes példányok által kezelt adatokat.

  • Beszerzés és kiadás. A SyncLock blokkok úgy viselkednek, mint egy Try...Finally olyan szerkezet, amelyben a Try blokk kizárólagos zárolást lockobject szerez be, és a Finally blokk felszabadítja azt. Emiatt a SyncLock blokk garantálja a zárolás feloldását, függetlenül attól, hogy hogyan lép ki a blokkból. Ez még kezeletlen kivétel esetén is igaz.

  • Keretrendszerhívások. A SyncLock blokk a névtérben lévő osztály és metódusok meghívásával Enter szerzi be és Exit oldja fel a Monitor kizárólagos zárolást System.Threading .

Programozási eljárások

A lockobject kifejezésnek mindig olyan objektumra kell kiértékelnie, amely kizárólag az osztályhoz tartozik. Deklarálnia kell egy objektumváltozót Private az aktuális példányhoz tartozó adatok védelméhez, vagy egy objektumváltozót Private Shared az összes példányra jellemző adatok védelméhez.

A kulcsszóval nem Me adhat meg zárolási objektumot a példányadatokhoz. Ha az osztályon kívüli kód hivatkozással rendelkezik az osztály egy példányára, akkor ezt a hivatkozást használhatja zárolási objektumként egy SyncLock olyan blokkhoz, amely teljesen eltér az Önétől, és védi a különböző adatokat. Ily módon az osztály és a másik osztály megakadályozhatja egymást a nem kapcsolódó SyncLock blokkok végrehajtásában. Hasonlóképpen a sztring zárolása is problémás lehet, mivel az ugyanazon sztringet használó folyamat bármely más kódja ugyanazt a zárolást fogja használni.

A metódust nem használhatja Me.GetType a megosztott adatok zárolási objektumának megadására. Ennek az az oka, hogy GetType mindig ugyanazt Type az objektumot adja vissza egy adott osztálynévhez. A külső kód meghívhatja GetType az osztályt, és beszerezheti a használt zárolási objektumot. Ez azt eredményezné, hogy a két osztály blokkolja egymást a blokkjaikból SyncLock .

Példák

Leírás

Az alábbi példa egy olyan osztályt mutat be, amely egyszerű üzenetlistát tart fenn. Egy tömbben lévő üzeneteket és a tömb utolsó használt elemét tárolja egy változóban. Az addAnotherMessage eljárás növeli az utolsó elemet, és tárolja az új üzenetet. Ezt a két műveletet az és az SyncLockEnd SyncLock utasítások védik, mivel az utolsó elem növekménye után az új üzenetet tárolni kell, mielőtt bármely más szál újra növektetheti az utolsó elemet.

Ha az simpleMessageList osztály az összes példánya között megosztott egy üzenetlistát, a változók messagesList és messagesLast a deklarálva Sharedlesznek. Ebben az esetben a változónak messagesLock is meg kell lennie Shared, hogy minden példány egyetlen zárolási objektumot használjon.

Kód

Class simpleMessageList
    Public messagesList() As String = New String(50) {}
    Public messagesLast As Integer = -1
    Private messagesLock As New Object
    Public Sub addAnotherMessage(ByVal newMessage As String)
        SyncLock messagesLock
            messagesLast += 1
            If messagesLast < messagesList.Length Then
                messagesList(messagesLast) = newMessage
            End If
        End SyncLock
    End Sub
End Class

Leírás

Az alábbi példa szálakat és SyncLock. Amíg az SyncLock utasítás jelen van, az utasításblokk kritikus szakasz, és balance soha nem lesz negatív szám. Megjegyzéseket fűzhet a SyncLock kulcsszavakhoz, így End SyncLock láthatja a kulcsszó kihagyásának SyncLock hatását.

Kód

Imports System.Threading

Module Module1

    Class Account
        Dim thisLock As New Object
        Dim balance As Integer

        Dim r As New Random()

        Public Sub New(ByVal initial As Integer)
            balance = initial
        End Sub

        Public Function Withdraw(ByVal amount As Integer) As Integer
            ' This condition will never be true unless the SyncLock statement
            ' is commented out:
            If balance < 0 Then
                Throw New Exception("Negative Balance")
            End If

            ' Comment out the SyncLock and End SyncLock lines to see
            ' the effect of leaving out the SyncLock keyword.
            SyncLock thisLock
                If balance >= amount Then
                    Console.WriteLine("Balance before Withdrawal :  " & balance)
                    Console.WriteLine("Amount to Withdraw        : -" & amount)
                    balance = balance - amount
                    Console.WriteLine("Balance after Withdrawal  :  " & balance)
                    Return amount
                Else
                    ' Transaction rejected.
                    Return 0
                End If
            End SyncLock
        End Function

        Public Sub DoTransactions()
            For i As Integer = 0 To 99
                Withdraw(r.Next(1, 100))
            Next
        End Sub
    End Class

    Sub Main()
        Dim threads(10) As Thread
        Dim acc As New Account(1000)

        For i As Integer = 0 To 9
            Dim t As New Thread(New ThreadStart(AddressOf acc.DoTransactions))
            threads(i) = t
        Next

        For i As Integer = 0 To 9
            threads(i).Start()
        Next
    End Sub

End Module

Megjegyzések

Lásd még