Безопасно ли вызывать 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. Я добавил код, и он, кажется, работает нормально, но я хочу убедиться, что я не открываю себя другому гоче, как Abort. Являются ли они нормальными для использования как с резьбой, так и без резьбы?
1 ответ
Да, безопасно использовать их в однопоточном коде.
Однако есть проблемы с вашим InternalCalculate
что позволит ему выполнять код одновременно. Каждый звонок InternalCalculate
создает новый Lock
объект. Synclock
будет блокировать потоки, только если они используют один и тот же объект, поэтому сделать Lock
переменная-член только для чтения.
Если затем вы выполняете несколько потоков, то второй, третий, четвертый и т. Д. Будут ждать, пока первый из них, чтобы получить блокировку, не выйдет из блока синхронизации. Тогда остальные пойдут. Так что, если это код, который должен выполняться только один раз, вы должны проверить шаблон двойной проверки блокировки.
Вместо добавления MemoryBarriers
для чтения / записи изменчивых данных, я бы предложил вам использовать System.Threading.Thread.VolatileRead
а также System.Threading.Thread.VolatileWrite
, Тогда вам не нужно помнить, в каком порядке выполнять чтение / запись.