SyncLock 문SyncLock Statement

블록을 실행 하기 전에 문 블록에 대 한 단독 잠금을 획득 합니다.Acquires an exclusive lock for a statement block before executing the block.

구문Syntax

SyncLock lockobject  
    [ block ]  
End SyncLock  

요소Parts

lockobject
필수 요소.Required. 개체 참조로 계산 되는 식입니다.Expression that evaluates to an object reference.

block
선택 사항입니다.Optional. 잠금을 획득할 때 실행할 문 블록입니다.Block of statements that are to execute when the lock is acquired.

End SyncLock
SyncLock 블록을 종료 합니다.Terminates a SyncLock block.

설명Remarks

SyncLock 문을 사용 하면 여러 스레드가 동시에 문 블록을 실행 하지 않습니다.The SyncLock statement ensures that multiple threads do not execute the statement block at the same time. SyncLock는 다른 스레드가 실행 하지 않을 때까지 각 스레드가 블록을 입력 하지 못하게 합니다.SyncLock prevents each thread from entering the block until no other thread is executing it.

SyncLock은 두 개 이상의 스레드에서 데이터를 동시에 업데이트 하지 않도록 보호 하는 데 가장 일반적으로 사용 됩니다.The most common use of SyncLock is to protect data from being updated by more than one thread simultaneously. 데이터를 조작 하는 문이 중단 없이 완료 되어야 하는 경우에는 SyncLock 블록 안에 배치 합니다.If the statements that manipulate the data must go to completion without interruption, put them inside a SyncLock block.

배타적 잠금으로 보호 되는 문 블록은 임계 영역이 라고도 합니다.A statement block protected by an exclusive lock is sometimes called a critical section.

규칙Rules

  • 분기.Branching. 블록 외부에서 SyncLock 블록으로 분기할 수 없습니다.You cannot branch into a SyncLock block from outside the block.

  • 잠금 개체 값입니다.Lock Object Value. lockobject 값은 Nothing수 없습니다.The value of lockobject cannot be Nothing. Lock 개체는 SyncLock 문에서 사용 하기 전에 만들어야 합니다.You must create the lock object before you use it in a SyncLock statement.

    SyncLock 블록을 실행 하는 동안 lockobject의 값을 변경할 수 없습니다.You cannot change the value of lockobject while executing a SyncLock block. 이 메커니즘을 사용 하려면 lock 개체가 변경 되지 않은 상태로 유지 되어야 합니다.The mechanism requires that the lock object remain unchanged.

  • SyncLock 블록에는 wait 연산자를 사용할 수 없습니다.You can't use the Await operator in a SyncLock block.

동작Behavior

  • 방법일.Mechanism. 스레드가 SyncLock 문에 도달 하면 lockobject 식을 계산 하 고 식에서 반환 하는 개체에 대 한 배타적 잠금을 획득할 때까지 실행을 일시 중단 합니다.When a thread reaches the SyncLock statement, it evaluates the lockobject expression and suspends execution until it acquires an exclusive lock on the object returned by the expression. 다른 스레드가 SyncLock 문에 도달 하면 첫 번째 스레드가 End SyncLock 문을 실행할 때까지 잠금을 획득 하지 않습니다.When another thread reaches the SyncLock statement, it does not acquire a lock until the first thread executes the End SyncLock statement.

  • 보호 된 데이터입니다.Protected Data. lockobject Shared 변수인 경우에는 다른 스레드가 실행 하는 동안 클래스의 모든 인스턴스에서 스레드가 SyncLock 블록을 실행할 수 없습니다.If lockobject is a Shared variable, the exclusive lock prevents a thread in any instance of the class from executing the SyncLock block while any other thread is executing it. 이는 모든 인스턴스 간에 공유 되는 데이터를 보호 합니다.This protects data that is shared among all the instances.

    lockobject 인스턴스 변수인 경우 (Shared아님) 잠금은 현재 인스턴스에서 실행 되는 스레드가 동일한 인스턴스의 다른 스레드와 동시에 SyncLock 블록을 실행 하지 않도록 합니다.If lockobject is an instance variable (not Shared), the lock prevents a thread running in the current instance from executing the SyncLock block at the same time as another thread in the same instance. 그러면 개별 인스턴스에 의해 유지 관리 되는 데이터가 보호 됩니다.This protects data maintained by the individual instance.

  • 취득 및 릴리스.Acquisition and Release. SyncLock 블록은 Try 블록이 lockobject에 대 한 배타적 잠금을 획득 하 고 Finally 블록이이를 해제 하는 Try...Finally 생성 처럼 동작 합니다.A SyncLock block behaves like a Try...Finally construction in which the Try block acquires an exclusive lock on lockobject and the Finally block releases it. 이로 인해 SyncLock 블록은 블록을 종료 하는 방법에 관계 없이 잠금 해제를 보장 합니다.Because of this, the SyncLock block guarantees release of the lock, no matter how you exit the block. 처리 되지 않은 예외의 경우에도 마찬가지입니다.This is true even in the case of an unhandled exception.

  • 프레임 워크 호출.Framework Calls. SyncLock 블록은 System.Threading 네임 스페이스에서 Monitor 클래스의 EnterExit 메서드를 호출 하 여 배타적 잠금을 획득 하 고 해제 합니다.The SyncLock block acquires and releases the exclusive lock by calling the Enter and Exit methods of the Monitor class in the System.Threading namespace.

프로그래밍 방법Programming Practices

lockobject 식은 항상 클래스에 독점적으로 속하는 개체로 계산 되어야 합니다.The lockobject expression should always evaluate to an object that belongs exclusively to your class. 현재 인스턴스에 속하는 데이터를 보호 하기 위해 Private 개체 변수를 선언 하거나 모든 인스턴스에 공통 된 데이터를 보호 하기 위해 Private Shared 개체 변수를 선언 해야 합니다.You should declare a Private object variable to protect data belonging to the current instance, or a Private Shared object variable to protect data common to all instances.

Me 키워드를 사용 하 여 인스턴스 데이터에 대 한 잠금 개체를 제공 하면 안 됩니다.You should not use the Me keyword to provide a lock object for instance data. 클래스 외부의 코드에 클래스의 인스턴스에 대 한 참조가 있는 경우 해당 참조를 다른 데이터를 보호 하는 것과 완전히 다른 SyncLock 블록의 잠금 개체로 사용할 수 있습니다.If code external to your class has a reference to an instance of your class, it could use that reference as a lock object for a SyncLock block completely different from yours, protecting different data. 이러한 방식으로 클래스와 다른 클래스는 관련 없는 SyncLock 블록을 실행 하지 못하도록 차단할 수 있습니다.In this way, your class and the other class could block each other from executing their unrelated SyncLock blocks. 동일한 문자열을 사용 하는 프로세스의 다른 코드가 동일한 잠금을 공유 하기 때문에 문자열에 대 한 잠금과 잠금은 문제가 될 수 있습니다.Similarly locking on a string can be problematic since any other code in the process using the same string will share the same lock.

또한 Me.GetType 메서드를 사용 하 여 공유 데이터에 대 한 잠금 개체를 제공 해서는 안 됩니다.You should also not use the Me.GetType method to provide a lock object for shared data. 이는 GetType 항상 지정 된 클래스 이름에 대해 같은 Type 개체를 반환 하기 때문입니다.This is because GetType always returns the same Type object for a given class name. 외부 코드는 클래스에서 GetType를 호출 하 고 사용 하는 것과 동일한 잠금 개체를 가져올 수 있습니다.External code could call GetType on your class and obtain the same lock object you are using. 이로 인해 두 클래스가 SyncLock 블록에서 서로 차단 됩니다.This would result in the two classes blocking each other from their SyncLock blocks.

Examples

설명Description

다음 예제에서는 간단한 메시지 목록을 유지 관리 하는 클래스를 보여 줍니다.The following example shows a class that maintains a simple list of messages. 배열에 있는 메시지와 해당 배열의 마지막으로 사용 된 요소를 변수에 저장 합니다.It holds the messages in an array and the last used element of that array in a variable. addAnotherMessage 프로시저는 마지막 요소를 증가 시키고 새 메시지를 저장 합니다.The addAnotherMessage procedure increments the last element and stores the new message. 이러한 두 작업은 SyncLockEnd SyncLock 문으로 보호 됩니다. 마지막 요소를 증가 시킨 후에는 새 메시지를 저장 해야 다른 스레드가 마지막 요소를 다시 증가 시킬 수 있습니다.Those two operations are protected by the SyncLock and End SyncLock statements, because once the last element has been incremented, the new message must be stored before any other thread can increment the last element again.

simpleMessageList 클래스가 모든 인스턴스 간에 메시지 목록 하나를 공유 하는 경우 변수 messagesListmessagesLastShared으로 선언 됩니다.If the simpleMessageList class shared one list of messages among all its instances, the variables messagesList and messagesLast would be declared as Shared. 이 경우 모든 인스턴스에서 사용 되는 단일 잠금 개체가 되도록 messagesLock 변수를 Shared해야 합니다.In this case, the variable messagesLock should also be Shared, so that there would be a single lock object used by every instance.

코드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

설명Description

다음 예제에서는 스레드와 SyncLock를 사용 합니다.The following example uses threads and SyncLock. SyncLock 문이 있으면 문 블록은 임계 섹션이 되며 balance 음수가 될 수 없습니다.As long as the SyncLock statement is present, the statement block is a critical section and balance never becomes a negative number. SyncLockEnd SyncLock 문을 주석으로 처리 하 여 SyncLock 키워드를 종료 하는 효과를 확인할 수 있습니다.You can comment out the SyncLock and End SyncLock statements to see the effect of leaving out the SyncLock keyword.

코드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

주석Comments

참고자료See also