SyncLock 语句

在执行块之前获取语句块的独占锁。

语法

SyncLock lockobject  
    [ block ]  
End SyncLock  

部件

lockobject
必填。 计算结果为对象引用的表达式。

block
可选。 获取锁时要执行的语句块。

End SyncLock
终止块 SyncLock

注解

SyncLock 语句可确保多个线程不会同时执行语句块。 SyncLock 防止每个线程进入块,直到没有其他线程执行它。

最常见的用途 SyncLock 是防止数据同时由多个线程更新。 如果作数据的语句必须进入完成状态且不会中断,请将这些语句放入块中 SyncLock

受排他锁保护的语句块有时称为 关键节

规则

  • 分支。 不能从块外部分支到 SyncLock 块。

  • 锁定对象值。 值 lockobject 不能 Nothing为 . 在语句中使用 SyncLock 锁对象之前,必须创建锁对象。

    在执行块时SyncLock,无法更改其值lockobject。 该机制要求锁对象保持不变。

  • 不能在块中使用 SyncLockAwait 运算符。

行为

  • 机制。 当线程到达 SyncLock 语句时,它会计算 lockobject 表达式并挂起执行,直到它获取表达式返回的对象上的排他锁。 当另一个线程到达语句时 SyncLock ,它不会获取锁,直到第一个线程执行 End SyncLock 该语句。

  • 受保护的数据。 如果 lockobjectShared 变量,排他锁可防止类的任何实例中的线程在执行块时执行 SyncLock 该块。 这会保护在所有实例之间共享的数据。

    如果 lockobject 实例变量(不是 Shared),则锁会阻止当前实例中运行的线程与同一实例中的另一个线程同时执行 SyncLock 该块。 这会保护单个实例维护的数据。

  • 获取和发布。 SyncLock块的行为类似于Try...Finally块获取Try独占锁lockobject的构造,块Finally释放它。 因此, SyncLock 无论如何退出块,块都保证释放锁。 即使在未经处理的异常的情况下也是如此。

  • 框架调用。 该SyncLock块通过调用Enter命名空间中的System.Threading类和Exit方法Monitor来获取和释放排他锁。

编程实践

表达式 lockobject 应始终计算为属于类的对象。 应声明一个 Private 对象变量来保护属于当前实例的数据,或者声明一个 Private Shared 对象变量来保护所有实例通用的数据。

不应使用 Me 关键字为实例数据提供锁定对象。 如果类外部的代码具有对类实例的引用,则它可以将该引用用作完全不同于你的块的锁对象 SyncLock ,从而保护不同的数据。 这样,你的类和其他类就可以互相阻止执行其无关 SyncLock 的块。 同样,对字符串的锁定可能会有问题,因为使用同一字符串的进程中的任何其他代码将共享同一锁。

不应使用 Me.GetType 该方法为共享数据提供锁定对象。 这是因为 GetType 始终返回给定类名的相同 Type 对象。 外部代码可以调用 GetType 类并获取所使用的同一锁对象。 这将导致两个类相互阻止其 SyncLock 块。

例子

DESCRIPTION

下面的示例演示了一个维护简单消息列表的类。 它在数组中保存消息,以及变量中该数组的最后一个已用元素。 该过程 addAnotherMessage 递增最后一个元素并存储新消息。 这两个作受 SyncLock 语句和 End SyncLock 语句的保护,因为一旦最后一个元素递增,必须先存储新消息,然后任何其他线程才能再次递增最后一个元素。

simpleMessageList如果类在其所有实例之间共享了一个消息列表,则变量messagesList将被messagesLast声明为 Shared。 在这种情况下, messagesLock 变量也应是 Shared,以便每个实例使用一个锁对象。

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。 只要 SyncLock 存在该语句,语句块就是关键节, balance 并且永远不会成为负数。 可以注释掉 SyncLockEnd SyncLock 语句以查看退出 SyncLock 关键字的效果。

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

注释

另请参阅