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不能是NothingThe value of lockobject cannot be Nothing. 您必須先將它用於建立之鎖定物件SyncLock陳述式。You must create the lock object before you use it in a SyncLock statement.

    您無法變更的值lockobject執行時SyncLock區塊。You cannot change the value of lockobject while executing a SyncLock block. 這個機制需要之鎖定物件維持不變。The mechanism requires that the lock object remain unchanged.

  • 您無法使用Await中的運算子SyncLock區塊。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. 如果lockobjectShared變數的獨佔鎖定可防止任何類別執行個體中的執行緒執行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. ASyncLock區塊的行為類似Try...Finally在其中建構Try區塊上取得的獨佔鎖定lockobjectFinally區塊釋放它。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. 這是即使發生未處理的例外狀況,則為 true。This is true even in the case of an unhandled exception.

  • 架構會呼叫。Framework Calls. SyncLock區塊會取得和釋放獨佔鎖定,藉由呼叫EnterExitMonitor類別System.Threading命名空間。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類別共用在所有執行個體,變數之間的訊息的一份messagesListmessagesLast會宣告為SharedIf 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

下列範例會使用執行緒和SyncLockThe 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