Правила поиска/избежания общих данных в многопоточном приложении
-
03-07-2019 - |
Вопрос
Эй,
как мы все знаем, разработка многопоточного приложения — сложная задача.Тем более вопрос, когда и что блокировать, ИМХО не столь очевиден.Часто я смотрю на метод/класс и должен спросить себя, делюсь ли я некоторыми данными, которые могут быть изменены несколькими потоками.И когда я не уверен, что это заканчивается блокировкой ( ) для всего блока кода.
Итак, что мне хотелось бы знать:Есть ли у вас предложения по шаблонам/правилам и т. д.для идентификации общих данных?Или методы, гарантирующие, что ваш код является потокобезопасным.
Например.:
- Статические методы не должны изменять поля класса.(Если только они не закроют поле.)
- Параметры метода ссылочного типа не должны передаваться «напрямую».Всегда передайте клон.
Кстати:
Microsoft Research работает над ШАХМАТЫ.Инструмент для поиска и воспроизведения ошибок Heisenbugs в параллельных программах.Я надеюсь, что это и PLINQ позволят улучшить разработку параллельных программ.
Решение
По возможности делайте свои типы неизменяемыми для начала.Тогда нет необходимости клонировать.Если вам нужно «изменить» содержимое объекта, заставьте метод вместо этого возвращать новый объект - точно так же, как String.Replace
и т. д. делает.
По сути, это стиль функционального программирования, и он прекрасен.К сожалению, у нас (в настоящее время) нет неизменяемых коллекций, встроенных в инфраструктуру .NET, хотя существуют сторонние коллекции, включая одного от нашего ДжаредПара.
Другие советы
Инкапсуляция данных в классе полезна для обеспечения потокобезопасности.Вы получаете контроль над тем, как осуществляется доступ к данным, и можете сделать класс ответственным за синхронизацию вместо того, чтобы код всего приложения пытался синхронизироваться должным образом.
Кроме того, вам нужно куда-то поместить частную переменную, которую можно использовать в качестве идентификатора блокировки, чтобы избежать использования самих данных в качестве идентификатора блокировки.Имея приватную переменную, выделенную в качестве идентификатора блокировки, вы устраняете один возможный источник взаимоблокировок.