代码之家  ›  专栏  ›  技术社区  ›  Maury Markowitz

即使不在单独的线程中,也可以安全地调用SyncLock和MemoryBarrier吗?

  •  0
  • Maury Markowitz  · 技术社区  · 8 年前

    后续行动 this post .我的目标是只有一个 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()
    

    我不清楚 the documentation 如果我在main中运行的代码中调用这些会发生什么。我已经添加了代码,它看起来运行正常,但我想确保我不会再遇到另一个问题,比如Abort。这些可以用于线程和非线程用途吗?

    1 回复  |  直到 7 年前
        1
  •  1
  •   FloatingKiwi    8 年前

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

    但是,您的 InternalCalculate 这将允许它同时执行代码。每次呼叫 内部计算 创建新的 Lock 对象 Synclock 仅当线程使用同一对象时才会阻塞线程 只读成员变量。

    如果然后执行多个线程,那么第二、第三、第四个线程等将等待第一个获取锁的线程退出同步锁块。然后其他人就走了。因此,如果这是只应执行一次的代码,则应检查双重检查锁定模式。

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