#vb.net #static #locking #thread-safety #shared
#vb.net #статические #блокировка #безопасность потоков #общий
Вопрос:
В следующем примере getList возвращает экземпляр статической (общей) переменной. Это нужно заблокировать, чтобы быть потокобезопасным.
Но как насчет doSomething, который не использует никаких статических переменных вне метода? Нужна ли блокировка тоже?
РЕДАКТИРОВАТЬ: я хотел бы уточнить, что в данном конкретном случае я ожидаю, что doSomething всегда будет последовательно печатать 0-100 (т. Е. Нет 0123745 …) независимо от количества вызывающих потоков. Или, в общем, разные потоки не влияют на переменные друг друга (вывод на консоль — это только пример). Язык в следующем примере VB.NET .
Как сказал paxdiablo:
В этом случае, похоже, единственное, что затронуто, — это локальная переменная i, которая будет иметь отдельную копию для каждого вызова функции. Другими словами, он не нуждается в защите.
Это именно то, что я пытался решить. Спасибо!
Public Class TestClass
Private Shared lock As New Object
Private Shared list As List(Of Integer)
Public Shared Function GetList() As List(Of Integer)
SyncLock lock
If list Is Nothing Then
list = New List(Of Integer)
End If
Return list
End SyncLock
End Function
Public Shared Sub DoSomething()
Dim i As Integer
For i = 0 To 100
Console.WriteLine(i.ToString)
Next
End Sub
End Class
Ответ №1:
Ну, это в основном будет зависеть от языка, который вы не указали, но, как правило, если код не затрагивает ресурс, который также может затронуть другой поток, его не нужно защищать.
В этом случае, похоже, единственное, что затронуто, — это локальная переменная i
, которая будет иметь отдельную копию для каждого вызова функции. Другими словами, он не нуждается в защите.
Конечно, можно утверждать, что консоль также является ресурсом и может нуждаться в защите, если, например, вы не хотите, чтобы строки мешали друг другу (синхронизировать запись) или хотели, чтобы все сто строк выводились как единое целое (синхронизировать весь цикл for).
Но на самом деле это не защитит консоль, а только блок кода, который ее использует. Другие потоки по-прежнему смогут выполнять запись в консоль, не используя этот метод.
Итог, я не думаю, что вам нужен synclock во втором методе.
Этот раздел ниже не имеет значения, если вы используете SyncLock в VB.Net (как сейчас, похоже, обстоит дело). Язык гарантирует, что блокировка будет снята независимо от того, как вы покидаете блок. Я оставлю это для истерических целей.
Я был бы немного обеспокоен вашим размещением synclock в первом методе, особенно если оператор return был передачей управления обратно вызывающему (и synclock не разблокировался автоматически при изменении области видимости). Похоже, вы можете вернуться без разблокировки, что было бы катастрофой. Я бы подумал, что более подходящим будет следующее:
Public Shared Function GetList() As List(Of Integer)
SyncLock lock
If list Is Nothing Then
list = New List(Of Integer)
End If
End SyncLock
Return list
End Function
Комментарии:
1. Я думаю, что @pst правильно переименовать как VB.Net .
Synclock
в VB. Net эквивалентенlock
в C # и имеет те же гарантии разблокировки
Ответ №2:
В общем, нет.
Вы должны четко понимать причину, по GetList
которой применяется блокировка. Это не так, как вы подразумеваете в своем первом предложении, потому что оно возвращает статическую переменную. Вы могли бы удалить код блокировки и GetList
все равно были бы потокобезопасными. Но с блокировкой есть дополнительная гарантия — список будет создан только один раз, и все вызывающие этот код получат ссылку на один и тот же список.
Ответ №3:
Почему бы вообще не избежать блокировки и просто сделать это:
Public Class TestClass
Private Shared lock As New Object
Private Shared list As New List(Of Integer)
Public Shared Function GetList() As List(Of Integer)
Return list
End Function
Public Shared Sub DoSomething()
Dim i As Integer
For i = 0 To 100
Console.WriteLine(i.ToString)
Next
End Sub
End Class
Комментарии:
1. Раздел getList упоминается только в качестве предисловия к части doSomething. Вероятно, я должен был пропустить это, поскольку это скорее сбивает с толку, чем проясняет.