다음을 통해 공유


SyncLock 문

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

문법

SyncLock lockobject  
    [ block ]  
End SyncLock  

부분

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

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

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

비고

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

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

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

규칙

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

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

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

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

행동

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

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

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

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

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

프로그래밍 사례

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

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

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

예시

설명

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

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

코드

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

설명

다음 예제에서는 스레드 및 SyncLock. 문이 있는 한 SyncLock 문 블록은 중요한 섹션이며 balance 음수가 되지 않습니다. 및 End SyncLock 문을 주석으로 SyncLock 처리하여 키워드를 제외 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

코멘트

참고하십시오