MSpec: Как сделать статические переменные потокобезопасными? - PullRequest
4 голосов
/ 18 января 2012

Я использую MSpec для моего последнего проекта, и в целом я действительно доволен им.Тем не менее, у меня есть проблема с параллелизмом, когда мои тесты выполняются в параллельном режиме, и мне интересно, сталкивался ли кто-нибудь с этой проблемой или, что еще лучше, имеет решение?

MSpec в значительной степени зависит от статических методов и переменных для работы.

Теперь, когда я определяю статические переменные в моих базовых классах, которые используются несколькими тестовыми классами, и я запускаю свои тесты в параллельном режиме, они показывают, что они имеют одни и те же статические переменные и, таким образом, мешают друг другу.

Я использую и NCrunch, и Resharper в качестве тест-раннеров, и я испытываю проблему в обоих.

Кто-нибудь знаком с этой проблемой?

Ответы [ 2 ]

1 голос
/ 18 января 2012

Во-первых, я бы порекомендовал прочитать Руководство по безопасности Thead на MSDN .Это даст вам хороший обзор того, как и почему сделать методы поточно-ориентированными в C #.

Следующие правила описывают рекомендации по проектированию для реализации потоков:

  • Избегайте предоставлениястатические методы, которые изменяют статическое состояние.В общих серверных сценариях статическое состояние совместно используется запросами, что означает, что несколько потоков могут выполнять этот код одновременно.Это открывает возможность для обсуждения ошибок.Подумайте об использовании шаблона проектирования, который инкапсулирует данные в экземпляры, которые не передаются между запросами.
  • ... Добавление блокировок для создания поточно-ориентированного кода снижает производительность, повышает конкуренцию за блокировку и создает возможность возникновения ошибок взаимоблокировки
  • Помните о вызовах методов в заблокированных разделах.Взаимные блокировки могут возникать, когда статический метод в классе A вызывает статические методы в классе B и наоборот.Если A и B синхронизируют свои статические методы, это приведет к взаимоблокировке.Вы можете обнаружить эту взаимоблокировку только при сильном потоке потока.
  • Помните о проблемах с оператором блокировки (SyncLock в Visual Basic).Заманчиво использовать оператор блокировки для решения всех проблем с потоками.Однако класс System.Threading.Interlocked лучше для обновлений, которые должны быть атомарными ...

Как общее примечание, методология, которую я предпочитаю использовать (где это возможно), состоит в том, чтобыметод (статический или иной) неизменный .Для этого все переменные должны быть локальными (создаваться локально в стеке или передаваться в качестве параметров методу).Обеспечивая использование только локальных переменных, или переменные-члены являются неизменными, каждый поток будет работать в своем собственном отделении, и изменения в переменных не будут влиять на другой поток.Эту методологию я широко использовал в программном обеспечении для моделирования .NET, чтобы обеспечить беспроблемную и, следовательно, высокопроизводительную многопоточность в C #.

В качестве альтернативы, если переменные должны быть переменными-членами, и изменяемый доступ к ним может быть защищен ключевыми словами блокировки.Будьте осторожны с использованием блокировки, которая вызовет переключение контекста (замедление) и создаст возможность возникновения тупиковой ситуации.Это также не гарантирует безопасность потоков, так как использование блокировки должно защищать от конкретного сценария, который вы пытаетесь предотвратить.

Для дальнейшего чтения я бы предложил посмотреть следующие связанные вопросы, которые описывают безопасность потоков и неизменность в C #:

С уважением,

0 голосов
/ 18 января 2012

Статические поля не являются потокобезопасными по умолчанию. Чтобы сделать их потокобезопасными, вы можете украсить их атрибутом [ThreadStatic].

Посмотрите ThreadStaticAttribute Class на MSDN для получения дополнительной информации.

...