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
@No__t_0 ブロックを終了します。Terminates a SyncLock block.

RemarksRemarks

@No__t_0 ステートメントを実行すると、複数のスレッドが同時にステートメントブロックを実行しなくなります。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.

@No__t_0 を使用する最も一般的な方法は、複数のスレッドによってデータが同時に更新されないように保護することです。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. @No__t_0 の値を Nothing することはできません。The value of lockobject cannot be Nothing. @No__t_0 ステートメントで使用する前に、lock オブジェクトを作成する必要があります。You must create the lock object before you use it in a SyncLock statement.

    @No__t_1 ブロックの実行中に lockobject の値を変更することはできません。You cannot change the value of lockobject while executing a SyncLock block. このメカニズムでは、ロックオブジェクトが変更されないようにする必要があります。The mechanism requires that the lock object remain unchanged.

  • @No__t_1 ブロックでAwait演算子を使用することはできません。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. @No__t_0 が 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.

    @No__t_0 がインスタンス変数 (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. @No__t_0 ブロックは、Try ブロックが lockobject に対して排他ロックを取得する Try...Finally の構築と同様に動作し、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. @No__t_0 ブロックは、System.Threading 名前空間の Monitor クラスの Enter および Exit メソッドを呼び出すことによって、排他ロックを取得し、解放します。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

@No__t_0 式は、常に、クラスにのみ属しているオブジェクトに評価される必要があります。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.

@No__t_0 キーワードを使用して、インスタンスデータ用のロックオブジェクトを指定しないでください。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. これにより、2つのクラスが 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. @No__t_0 プロシージャは、最後の要素をインクリメントし、新しいメッセージを格納します。The addAnotherMessage procedure increments the last element and stores the new message. これら2つの操作は、SyncLock および End 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.

@No__t_0 クラスがすべてのインスタンス間で1つのメッセージリストを共有している場合、messagesListmessagesLast の変数は Shared として宣言されます。If the simpleMessageList class shared one list of messages among all its instances, the variables messagesList and messagesLast would be declared as Shared. この場合、すべてのインスタンスで1つのロックオブジェクトが使用されるように、変数 messagesLockShared する必要があります。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. @No__t_0 ステートメントが存在する限り、ステートメントブロックはクリティカルセクションであり balance 負の値になることはありません。As long as the SyncLock statement is present, the statement block is a critical section and balance never becomes a negative number. @No__t_0 と End 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