Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Hämtar ett exklusivt lås för ett instruktionsblock innan blocket körs.
Syntax
SyncLock lockobject
[ block ]
End SyncLock
Delar
lockobject
Obligatoriskt. Uttryck som utvärderas till en objektreferens.
block
Valfritt. Block med instruktioner som ska köras när låset hämtas.
End SyncLock
Avslutar ett SyncLock block.
Anmärkningar
-instruktionen SyncLock ser till att flera trådar inte kör instruktionsblocket samtidigt.
SyncLock förhindrar att varje tråd kommer in i blocket förrän ingen annan tråd kör den.
Den vanligaste användningen av SyncLock är att skydda data från att uppdateras av mer än en tråd samtidigt. Om de instruktioner som manipulerar data måste slutföras utan avbrott placerar du dem i ett SyncLock block.
Ett instruktionsblock som skyddas av ett exklusivt lås kallas ibland för ett kritiskt avsnitt.
Reglemente
Förgrening. Du kan inte förgrena dig till ett
SyncLockblock utanför blocket.Lås objektvärde. Värdet för
lockobjectfår inte varaNothing. Du måste skapa låsobjektet innan du använder det i enSyncLock-instruktion.Du kan inte ändra värdet
lockobjectför när du kör ettSyncLockblock. Mekanismen kräver att låsobjektet förblir oförändrat.Du kan inte använda Await-operatorn i ett
SyncLockblock.
Beteende
Mekanism. När en tråd når -instruktionen
SyncLockutvärderar den uttrycket och pausar körningenlockobjecttills den hämtar ett exklusivt lås på objektet som returneras av uttrycket. När en annan tråd når -instruktionenSyncLockhämtar den inte ett lås förrän den första tråden kör -instruktionenEnd SyncLock.Skyddade data. Om
lockobjectär enSharedvariabel förhindrar det exklusiva låset att en tråd i någon instans av klassen körSyncLockblocket medan någon annan tråd kör den. Detta skyddar data som delas mellan alla instanser.Om
lockobjectär en instansvariabel (inteShared) förhindrar låset att en tråd som körs i den aktuella instansenSyncLockkör blocket samtidigt som en annan tråd i samma instans. Detta skyddar data som underhålls av den enskilda instansen.Förvärv och lansering. Ett
SyncLockblock beter sig som enTry...Finallykonstruktion därTryblocket hämtar ett exklusivt lås pålockobjectochFinallyblocket släpper det. På grund av dettaSyncLockgaranterar blocket att låset släpps, oavsett hur du avslutar blocket. Detta gäller även i händelse av ett ohanterat undantag.Framework-anrop. Blocket
SyncLockhämtar och släpper det exklusiva låset genom att anropa klassmetodernaEnterMonitorochExiti System.Threading namnområdet.
Programmeringsmetoder
Uttrycket lockobject bör alltid utvärderas till ett objekt som uteslutande tillhör din klass. Du bör deklarera en Private objektvariabel för att skydda data som tillhör den aktuella instansen eller en Private Shared objektvariabel för att skydda data som är gemensamma för alla instanser.
Du bör inte använda nyckelordet Me för att ange ett låsobjekt för instansdata. Om kod som är extern för klassen har en referens till en instans av klassen kan den använda den referensen som ett låsobjekt för ett SyncLock block som är helt annorlunda än ditt, vilket skyddar olika data. På så sätt kan din klass och den andra klassen blockera varandra från att köra sina orelaterade SyncLock block. På samma sätt kan det vara problematiskt att låsa en sträng eftersom all annan kod i processen som använder samma sträng delar samma lås.
Du bör inte heller använda Me.GetType metoden för att ange ett låsobjekt för delade data. Det beror på att GetType alltid returnerar samma Type objekt för ett visst klassnamn. Extern kod kan anropa GetType din klass och hämta samma låsobjekt som du använder. Detta skulle resultera i att de två klasserna blockerar varandra från sina SyncLock block.
Exempel
Beskrivning
I följande exempel visas en klass som upprätthåller en enkel lista med meddelanden. Den innehåller meddelandena i en matris och det senast använda elementet i matrisen i en variabel. Proceduren addAnotherMessage ökar det sista elementet och lagrar det nya meddelandet. Dessa två åtgärder skyddas av instruktionen SyncLock och End SyncLock eftersom när det sista elementet har ökats måste det nya meddelandet lagras innan någon annan tråd kan öka det sista elementet igen.
simpleMessageList Om klassen delade en lista med meddelanden mellan alla sina instanser deklareras variablerna messagesList och messagesLast som Shared. I det här fallet bör variabeln messagesLock också vara Shared, så att det skulle finnas ett enda låsobjekt som används av varje instans.
Kod
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
Beskrivning
I följande exempel används trådar och SyncLock. Så länge instruktionen SyncLock finns är instruktionsblocket ett kritiskt avsnitt och balance blir aldrig ett negativt tal. Du kan kommentera ut instruktionen SyncLock och End SyncLock för att se effekten av att utelämna nyckelordet SyncLock .
Kod
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