SyncLock — Instrukcja

Uzyskuje blokadę wyłączności dla bloku instrukcji przed wykonaniem bloku.

SyncLock lockobject
    [ block ]
End SyncLock

Części

  • lockobject
    Wymagane.Wyrażenie, którego wynikiem jest odwołanie do obiektu.

  • block
    Opcjonalne.Blok instrukcji, które są po blokady.

  • End SyncLock
    Kończy SyncLock bloku.

Uwagi

SyncLock Instrukcji gwarantuje, że wiele wątków nie wykonanie instrukcji bloku w tym samym czasie.SyncLockKażdy wątek uniemożliwia wprowadzanie bloku aż żaden inny wątek jest on wykonywany.

Najczęściej z SyncLock jest ochrona danych przed aktualizowany przez więcej niż jeden wątek jednocześnie.Jeśli w instrukcji, które manipulowania danymi, należy przejść do zakończenia bez przerwy, umieść je wewnątrz SyncLock bloku.

Chronione przez blokadę wyłączności blok instrukcji jest czasami nazywany sekcji krytycznej.

Zasady

  • Rozgałęzianie.Nie Rozgałęzienie do SyncLock zablokować z poza blokiem.

  • Zablokuj wartości obiektu.Wartość lockobject nie może być Nothing.Należy utworzyć obiekt Zablokuj przed użyciem go w SyncLock instrukcji.

    Nie można zmienić wartości lockobject podczas wykonywania SyncLock bloku.Mechanizm wymaga, aby zablokować obiektu pozostają niezmienione.

  • Nie można użyć Await operatora w SyncLock bloku.

Zachowanie

  • Mechanizm.Gdy wątek osiągnie SyncLock wynikiem instrukcji, lockobject wyrażenie i zawiesza wykonywanie aż kupuje blokadę wyłączności na obiekt zwrócony przez wyrażenie.Gdy inny wątek osiągnie SyncLock instrukcji, to nie nabywa blokady aż pierwszy wątek wykonuje End SyncLock instrukcji.

  • Chronionych danych.Jeśli lockobject jest Shared zmiennej, blokada wyłączności uniemożliwia wątek w dowolnej instancji klasy wykonywanie SyncLock blokowanie, podczas gdy inny wątek jest on wykonywany.Chroni to dane wspólne wszystkich instancji.

    Jeśli lockobject jest zmienną instancji (nie Shared), Blokada zapobiega wątek działający w bieżącej instancji wykonywanie SyncLock bloku jednocześnie inny wątek w tym samym wystąpieniu.Chroni to dane obsługiwane przez poszczególnych instancji.

  • Nabycie i wydania.A SyncLock bloku zachowuje się jak Try...Finally konstrukcji, w którym Try bloku przejmuje wyłączną blokadę na lockobject i Finally zwolni blok.W związku z tym SyncLock bloku gwarancje release blokady, niezależnie od tego, jak zakończyć bloku.Jest to nawet w przypadku nieobsłużonego wyjątku.

  • Ramy wywołań.SyncLock Bloku nabywa i zwalnia blokadę wyłączności przez wywołanie Enter i Exit metody Monitor klasy w System.Threading obszaru nazw.

Programowanie praktyk

lockobject Wyrażenia powinna zawsze być obiekt, który należy wyłącznie do swojej klasy.Należy zadeklarować Private zmienną obiektu, aby chronić dane należące do bieżącego wystąpienia lub Private Shared zmienną obiektu, aby chronić dane wspólne dla wszystkich wystąpień.

Nie należy używać Me słowo kluczowe, aby zapewnić blokady, na przykład obiekt danych.Jeśli kod zewnętrzny względem klasy zawiera odwołanie do instancji klasy, można użyć tego odwołania jako obiekt blokady dla SyncLock bloku całkowicie różna od zamierzonej, ochrona różnych danych.W ten sposób klasy i inne klasy może blokować wzajemnie wykonywanie ich niepowiązanych SyncLock bloków.Podobnie blokowania na ciąg może być problematyczne, ponieważ inny kod procesu przy użyciu samego ciągu będzie udostępniać blokadę.

Ponadto nie należy korzystać z Me.GetType metodę w celu zapewnienia zablokować obiektu dla udostępnianych danych.Wynika to z GetType zawsze zwraca to samo Type nazwę danej klasy obiektu.Kod zewnętrzny może wywołać GetType w klasie i uzyskania są przy użyciu tego samego obiektu blokady.Spowodowałoby to dwie klasy blokowania innych z ich SyncLock bloków.

Przykłady

Opis

Poniższy przykład pokazuje klasy, która utrzymuje proste listy wiadomości.Przechowuje wiadomości w tablicy i ostatni używany element tablicy w zmiennej.addAnotherMessage Procedury zwiększa ostatni element i zapisuje nowe wiadomości.Te dwie operacje są chronione przez SyncLock i End SyncLock instrukcji, ponieważ po ostatnim elementem została zwiększona, nowe wiadomości muszą być przechowywane przed inny wątek może zwiększać ostatni element ponownie.

Jeśli simpleMessageList klasy udostępnione jednej listy wiadomości między wszystkie jego wystąpienia, zmienne messagesList i messagesLast mogłyby być zadeklarowany jako Shared.W przypadku zmiennej messagesLock może być również Shared, dzięki czemu będzie obiekt pojedynczej blokady używane przez każde wystąpienie.

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

Opis

Poniższy przykład używa wątków i SyncLock.Tak długo, jak SyncLock deklaracji, instrukcji bloku jest sekcji krytycznej i balance nigdy nie staje się liczbę ujemną.Można wykomentować SyncLock i End SyncLock instrukcji, aby zobaczyć efekt pomijając SyncLock słowa kluczowego.

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

Zobacz też

Informacje

System.Threading

Monitor

Synchronizacja wątku (C# i Visual Basic)

Inne zasoby

Wątkowość (C# i Visual Basic)