SyncLock 문

블록을 실행하기 전에 문 블록에 대한 단독 잠금을 획득합니다.

Syntax

SyncLock lockobject  
    [ block ]  
End SyncLock  

부분

lockobject
필수 사항입니다. 개체 참조로 계산되는 식입니다.

block
선택 사항입니다. 잠금을 획득할 때 실행할 문 블록입니다.

End SyncLock
블록을 종료합니다 SyncLock .

설명

문을 SyncLock 통해 여러 스레드가 문 블록을 동시에 실행하지 않도록 합니다. SyncLock 는 다른 스레드가 실행되지 않을 때까지 각 스레드가 블록에 들어가지 못하게 합니다.

의 가장 일반적인 용도 SyncLock 는 둘 이상의 스레드에서 동시에 데이터를 업데이트하지 않도록 보호하는 것입니다. 데이터를 조작하는 문이 중단 없이 완료되어야 하는 경우 블록 안에 SyncLock 넣습니다.

전용 잠금으로 보호되는 문 블록을 중요한 섹션이라고도 합니다.

규칙

  • 분기. 블록 외부에서 블록으로 SyncLock 분기할 수 없습니다.

  • 개체 값을 잠급니다. 의 lockobject 값은 일 수 없습니다 Nothing. 문에서 잠금 개체를 사용하려면 먼저 잠금 개체를 SyncLock 만들어야 합니다.

    블록을 실행하는 SyncLock 동안 값은 lockobject 변경할 수 없습니다. 메커니즘을 사용하려면 잠금 개체가 변경되지 않은 상태로 유지되어야 합니다.

  • 블록에서는 Await 연산자를 SyncLock 사용할 수 없습니다.

동작

  • 메커니즘. 스레드가 문에 SyncLock 도달하면 식을 평가하고 식에서 lockobject 반환된 개체에 대한 배타적 잠금을 획득할 때까지 실행을 일시 중단합니다. 다른 스레드가 문에 SyncLock 도달하면 첫 번째 스레드가 문을 실행할 때까지 잠금을 End SyncLock 획득하지 않습니다.

  • 보호된 데이터입니다. 가 변수인 Shared 경우 lockobject 배타적 잠금은 클래스의 모든 instance 스레드가 블록을 실행하는 동안 다른 스레드가 블록을 실행하는 SyncLock 것을 방지합니다. 이렇게 하면 모든 인스턴스 간에 공유되는 데이터가 보호됩니다.

    가 instance 변수(가 아님Shared)인 경우 lockobject 잠금은 현재 instance 실행 중인 스레드가 동일한 instance 다른 스레드와 동시에 블록을 실행하는 SyncLock 것을 방지합니다. 이렇게 하면 개별 instance 유지 관리되는 데이터가 보호됩니다.

  • 취득 및 릴리스. 블록은 SyncLock 블록이 Try...Finally 배타적 잠금 lockobject 을 획득하고 블록이 Finally 해제하는 생성 Try 처럼 동작합니다. 이 때문에 블록은 SyncLock 블록을 종료하는 방법에 관계없이 잠금 해제를 보장합니다. 처리되지 않은 예외의 경우에도 마찬가지입니다.

  • 프레임워크 호출. 블록은 SyncLock 네임스페이스에서 클래스의 및 메서드를 Enter 호출하여 배타적 잠금을 MonitorSystem.Threading 획득하고 Exit 해제합니다.

프로그래밍 사례

식은 lockobject 항상 클래스에만 속하는 개체로 평가되어야 합니다. 현재 instance 속한 데이터를 보호하기 위해 개체 변수를 선언하거나 개체 변수를 Private Shared 선언 Private 하여 모든 인스턴스에 공통된 데이터를 보호해야 합니다.

키워드(keyword) 사용하여 Me instance 데이터에 대한 잠금 개체를 제공해서는 안 됩니다. 클래스 외부의 코드에 클래스의 instance 대한 참조가 있는 경우 해당 참조를 사용자와 완전히 다른 블록의 SyncLock 잠금 개체로 사용하여 다른 데이터를 보호할 수 있습니다. 이러한 방식으로 클래스와 다른 클래스는 서로 관련 없는 SyncLock 블록을 실행하지 못하도록 차단할 수 있습니다. 마찬가지로 동일한 문자열을 사용하는 프로세스의 다른 코드가 동일한 잠금을 공유하므로 문자열에 대한 잠금은 문제가 될 수 있습니다.

또한 메서드를 Me.GetType 사용하여 공유 데이터에 대한 잠금 개체를 제공하지 않아야 합니다. 지정된 클래스 이름에 대해 항상 동일한 Type 개체를 반환하기 때문 GetType 입니다. 외부 코드는 클래스에서 를 호출 GetType 하고 사용 중인 것과 동일한 잠금 개체를 가져올 수 있습니다. 이로 인해 두 클래스가 블록에서 서로를 차단합니다 SyncLock .

예제

Description

다음 예제에서는 메시지의 간단한 목록을 유지 관리 하는 클래스를 보여 줍니다. 배열의 메시지와 변수에서 해당 배열의 마지막으로 사용된 요소를 보유합니다. 프로시저는 addAnotherMessage 마지막 요소를 증가시키고 새 메시지를 저장합니다. 마지막 요소가 증가하면 다른 스레드가 마지막 요소를 다시 증가하기 전에 새 메시지를 저장해야 하므로 이러한 두 작업은 및 End SyncLock 문으로 보호 SyncLock 됩니다.

클래스가 simpleMessageList 모든 인스턴스 간에 메시지 목록을 공유하면 변수 및 messagesListmessagesLast 가 로 Shared선언됩니다. 이 경우 변수 messagesLockShared모든 instance 사용되는 단일 잠금 개체가 있도록 이어야 합니다.

코드

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

Description

다음 예제에서는 스레드 및 SyncLock를 사용합니다. 문이 있는 한 SyncLock 문 블록은 중요한 섹션이며 balance 음수가 되지 않습니다. 및 End SyncLock 문을 주석으로 SyncLock 처리하여 키워드(keyword) 제외 SyncLock 하는 효과를 확인할 수 있습니다.

코드

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

주석

참고 항목