调用 SyncLock 和 MemoryBarrier 是否安全,即使您不在单独的线程中?



这篇文章的后续。我的目标是一次只有一个Calculate,所以我添加了一个SyncLock:

Public Sub Calculate(Optional inBack As Boolean = True)
    If Not inBack Then
        InternalCalculate(-1, False)
    Else
        If CalcThread IsNot Nothing Then
            CalcThread.Abort() ' yes, I will replace this
            CalcThread = Nothing ' XXX
        End If
        If CalcThread Is Nothing Then
            CalcThread = New Threading.Thread(AddressOf InternalCalculate)
            CalcThread.IsBackground = True
        End If
        CalcThread.Start()
    End If
End Sub
Private Sub InternalCalculate(Optional Line As Integer = -1, Optional isBack As Boolean = True)
    Dim Lock As New Object
    SyncLock Lock
         Threading.Thread.MemoryBarrier() ' do this BEFORE a write, right?
         isRunning = true
        'do the expensive stuff
    End SyncLock
End Sub

注意isBack。如果这是假的,代码应该只在main中运行。这通常用于重新计算单个Line。我的问题是关于这两行代码的安全性:

SyncLock Lock
Threading.Thread.MemoryBarrier()

在文档中我不清楚如果我在main中运行的代码中调用这些会发生什么。我已经添加了代码,它似乎运行正常,但我想确保我没有打开自己的另一个gotcha,如中止。这些对线程和非线程使用都是OK的吗?

在单线程代码中使用它们是安全的。

有问题,但是你的InternalCalculate将允许它并发地执行代码。每次调用InternalCalculate都会创建一个新的Lock对象。Synclock只会阻塞使用相同对象的线程,所以将Lock设置为只读成员变量。

如果你执行多个线程,那么第二个,第三个,第四个等将等待,直到第一个获得锁退出同步锁块。然后其他人就会离开。因此,如果这是只应该执行一次的代码,您应该检查双重检查锁定模式。

而不是添加MemoryBarriers读/写易失性数据,我建议你使用System.Threading.Thread.VolatileReadSystem.Threading.Thread.VolatileWrite。这样你就不需要记住读/写的顺序了。

最新更新