Безопасно ли вызывать 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, Тогда вам не нужно помнить, в каком порядке выполнять чтение / запись.

Другие вопросы по тегам