Delen via


SyncLock-instructie

Hiermee verkrijgt u een exclusieve vergrendeling voor een instructieblok voordat u het blok uitvoert.

Syntaxis

SyncLock lockobject  
    [ block ]  
End SyncLock  

generator

lockobject
Vereist. Expressie die resulteert in een objectverwijzing.

block
Optioneel. Blok met instructies die moeten worden uitgevoerd wanneer de vergrendeling wordt verkregen.

End SyncLock
Hiermee wordt een SyncLock blok beëindigd.

Opmerkingen

De SyncLock instructie zorgt ervoor dat meerdere threads het instructieblok niet tegelijkertijd uitvoeren. SyncLock voorkomt dat elke thread het blok invoert totdat er geen andere thread wordt uitgevoerd.

Het meest voorkomende gebruik van SyncLock is om gegevens te beschermen tegen het tegelijkertijd bijwerken van meer dan één thread. Als de instructies waarmee de gegevens worden bewerkt, zonder onderbreking moeten worden voltooid, plaatst u deze in een SyncLock blok.

Een instructieblok dat wordt beveiligd door een exclusieve vergrendeling, wordt ook wel een kritieke sectie genoemd.

Regels

  • Vertakking. U kunt niet vertakken naar een SyncLock blok van buiten het blok.

  • Objectwaarde vergrendelen. De waarde van lockobject kan niet zijn Nothing. U moet het vergrendelingsobject maken voordat u het in een SyncLock instructie gebruikt.

    U kunt de waarde van het uitvoeren van lockobject een SyncLock blok niet wijzigen. Het mechanisme vereist dat het vergrendelingsobject ongewijzigd blijft.

  • U kunt de operator Await niet in een SyncLock blok gebruiken.

Gedrag

  • Mechanisme. Wanneer een thread de SyncLock instructie bereikt, wordt de expressie geëvalueerd en wordt de lockobject uitvoering onderbroken totdat er een exclusieve vergrendeling wordt verkregen voor het object dat door de expressie wordt geretourneerd. Wanneer een andere thread de SyncLock instructie bereikt, krijgt deze pas een vergrendeling als de eerste thread de End SyncLock instructie uitvoert.

  • Beveiligde gegevens. Als lockobject dit een Shared variabele is, voorkomt de exclusieve vergrendeling dat een thread in een exemplaar van de klasse het SyncLock blok uitvoert terwijl een andere thread deze uitvoert. Hiermee worden gegevens beveiligd die worden gedeeld tussen alle exemplaren.

    Als lockobject dit een exemplaarvariabele is (niet Shared), voorkomt de vergrendeling dat een thread die wordt uitgevoerd in het huidige exemplaar het SyncLock blok tegelijkertijd uitvoert als een andere thread in hetzelfde exemplaar. Hiermee worden gegevens beschermd die worden onderhouden door het afzonderlijke exemplaar.

  • Overname en release. Een SyncLock blok gedraagt zich als een Try...Finally constructie waarin het Try blok een exclusieve vergrendeling verwerft lockobject en het Finally blok het vrijgeeft. Hierdoor garandeert het blok de SyncLock release van de vergrendeling, ongeacht hoe u het blok afsluit. Dit geldt zelfs in het geval van een onverwerkte uitzondering.

  • Framework-aanroepen. Het SyncLock blok verkrijgt en publiceert de exclusieve vergrendeling door de Enter en Exit methoden van de Monitor klasse in de System.Threading naamruimte aan te roepen.

Programmeerprocedures

De lockobject expressie moet altijd evalueren naar een object dat exclusief bij uw klasse hoort. U moet een Private objectvariabele declareren om gegevens te beveiligen die behoren tot het huidige exemplaar of een Private Shared objectvariabele om gegevens te beveiligen die voor alle exemplaren gebruikelijk zijn.

Gebruik het Me trefwoord niet om een vergrendelingsobject voor exemplaargegevens op te geven. Als code buiten uw klasse een verwijzing heeft naar een exemplaar van uw klasse, kan deze verwijzing worden gebruikt als een vergrendelingsobject voor een SyncLock blok dat volledig verschilt van die van u, waardoor verschillende gegevens worden beveiligd. Op deze manier kunnen uw klas en de andere klasse elkaar blokkeren om hun niet-gerelateerde SyncLock blokken uit te voeren. Het vergrendelen van een tekenreeks kan ook problematisch zijn, omdat elke andere code in het proces die dezelfde tekenreeks gebruikt, dezelfde vergrendeling deelt.

U moet ook niet de Me.GetType methode gebruiken om een vergrendelingsobject voor gedeelde gegevens op te geven. Dit komt doordat GetType altijd hetzelfde Type object wordt geretourneerd voor een bepaalde klassenaam. Externe code kan uw klasse aanroepen GetType en hetzelfde vergrendelingsobject verkrijgen dat u gebruikt. Dit zou ertoe leiden dat de twee klassen elkaar van hun SyncLock blokken blokkeren.

Voorbeelden

Beschrijving

In het volgende voorbeeld ziet u een klasse die een eenvoudige lijst met berichten onderhoudt. Deze bevat de berichten in een matrix en het laatst gebruikte element van die matrix in een variabele. Met de addAnotherMessage procedure wordt het laatste element verhoogd en wordt het nieuwe bericht opgeslagen. Deze twee bewerkingen worden beveiligd door de SyncLock en End SyncLock instructies, omdat nadat het laatste element is verhoogd, het nieuwe bericht moet worden opgeslagen voordat een andere thread het laatste element opnieuw kan verhogen.

Als de simpleMessageList klasse één lijst met berichten over alle exemplaren heeft gedeeld, worden de variabelen messagesListmessagesLast gedeclareerd als Shared. In dit geval moet de variabele messagesLock ook zijn Shared, zodat er één vergrendelingsobject wordt gebruikt door elk exemplaar.

Code

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

Beschrijving

In het volgende voorbeeld worden threads en SyncLock. Zolang de SyncLock instructie aanwezig is, is het instructieblok een kritieke sectie en balance wordt het nooit een negatief getal. U kunt opmerkingen toevoegen aan de SyncLock en End SyncLock instructies om het effect van het weglaten van het SyncLock trefwoord te zien.

Code

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

Opmerkingen

Zie ook