0

这篇文章的后续。我的目标是一次只有一个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 中运行的代码中调用这些会发生什么。我已经添加了代码,它似乎运行正常,但我想确保我不会向另一个问题敞开心扉,比如 Abort。这些对于线程和非线程使用都可以吗?

4

1 回答 1

1

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

但是,您的问题InternalCalculate将允许它同时执行代码。每次调用InternalCalculate都会创建一个新Lock对象。Synclock如果这些线程使用相同的对象,则只会阻塞线程,因此请创建Lock一个只读成员变量。

如果您随后执行多个线程,则第二个、第三个、第四个等将等到第一个获得锁的线程退出同步锁块。然后其他人会去。因此,如果这是只应执行一次的代码,则应检查双重检查锁定模式。

MemoryBarriers我建议您不要添加用于读取/写入易失性数据,而是使用System.Threading.Thread.VolatileReadand System.Threading.Thread.VolatileWrite。然后你不需要记住读/写的顺序。

于 2016-09-21T21:16:14.680 回答