Каково различие между 'Synclock syncroot' и 'SyncLock Меня'?

vb. Сетевой вопрос о многопоточности:

Между чем различие

SyncLock syncRoot  
  ''# Do Stuff  
End SyncLock

- и -

SyncLock Me  
  ''# Do Stuff  
End SyncLock
5
задан Michael Haren 18 May 2010 в 15:14
поделиться

3 ответа

Весь код, который происходит в блоке SyncLock , синхронизируется со всем остальным кодом, происходящим в блоке SyncLock того же объекта . Очевидно, Me - это не то же самое, что syncRoot (то есть, я предполагаю, Me.SyncRoot , если ваш Me ICollection ).

Код, происходящий в блоке SyncLock одного объекта, не будет синхронизироваться с кодом в блоке SyncLock другого объекта.

Допустим, у вас есть этот код:

' happening on thread 1 '
SyncLock myColl.SyncRoot
    myColl.Add(myObject)
End SyncLock

' happening on thread 2 '
SyncLock myColl.SyncRoot
    myColl.Remove(myObject)
End SyncLock

Вышеупомянутое нормально: вызовы Add и Remove синхронизированы, то есть они не будут выполняться одновременно (в зависимости от того, что вызывается первым, будет выполнено , а второй не будет выполняться, пока не будет завершен первый).

Но предположим, что вместо этого у вас было следующее:

' happening on thread 1 '
SyncLock myColl.SyncRoot
    myColl.Add(myObject)
End SyncLock

' happening on thread 2 '
SyncLock myColl ' NOTE: SyncLock on a different object '
    myColl.Remove(myObject)
End SyncLock

Вышеупомянутые вызовы Add и Remove не синхронизированы каким-либо образом, формой или формой. Таким образом, в приведенном выше коде нет потоковой безопасности.

Итак, почему существует SyncRoot ? Все очень просто, потому что имеет смысл синхронизировать в наименьшем необходимом масштабе; т.е. нет необходимости синхронизировать код, который на самом деле не нуждается в синхронизации.

Рассмотрим следующий пример:

' happening on thread 1 '
SyncLock myColl
    myColl.Add(myObject)
End SyncLock

' happening on thread 2 '
SyncLock myColl
    ' Why you would have code like this, I do not know; '
    ' this is just for illustration. '
    myColl.Name = myColl.Name.Replace("Joe", "Bill")
End SyncLock

' happening on thread 3 '
SyncLock myColl
    myColl.Name = myColl.Name.Replace("Bill", "Joe")
End SyncLock

В приведенном выше примере вы синхронизируете больше, чем необходимо . Вызов Add действительно не имеет ничего общего с переименованием объекта myColl ; таким образом, код не нужно синхронизировать.

В этом заключается идея свойства SyncRoot : оно дает вам объект, вся цель которого - предоставить общий объект, с которым могут быть синхронизированы модификации / перечисления коллекции. Код, который включает коллекцию каким-то другим способом - но который не требует синхронизации с кодом, который изменяет или считывает содержимое коллекции - должен быть синхронизирован, где это необходимо. , на другом объекте.

5
ответ дан 13 December 2019 в 22:03
поделиться

Вы блокируете разные объекты.

Если другие части вашего кода (или внутренний код) синхронизируются на SyncRoot, что и должно быть, то вы ломаете вещи (т.е. вносите ошибки в потоки), синхронизируясь на Me.

Вы определенно должны синхронизироваться на SyncRoot- вот почему он там.

2
ответ дан 13 December 2019 в 22:03
поделиться

Если Object.ReferenceEquals(syncRoot, Me) = True, то ничего не изменилось. В противном случае блокировка приобретается с использованием разных объектов.

Если ваше использование syncRoot эквивалентно ICollection.SyncRoot, то блокировка будет получена с помощью того же объекта, который используется внутри коллекции для собственной блокировки. Это позволяет синхронизировать доступ к перечислителям. Например:

SyncLock collection.SyncRoot
  For Each item As Object in collection
  Next
End SyncLock

По традиции разработчики .NET избегают использовать Me в качестве объекта блокировки. Это особенно верно, если Me ссылается на объект, который виден в публичном API библиотеки классов. Мы избегаем этого потому, что другой код может использовать тот же объект для получения блокировки по причине, которая конфликтует с семантическим поведением, которое вы пытаетесь реализовать в своем коде. Этот конфликт может привести к узким местам или даже к тупиковым ситуациям.

Следует отметить, что SyncLock не синхронизирует доступ к самому объекту блокировки, а скорее к коду, обернутому конструкцией SyncLock. Другими словами, код, который охраняется SyncLock, использующим тот же объект, эффективно сериализуется.

3
ответ дан 13 December 2019 в 22:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: