Как обеспечить потокобезопасность в статическом методе

#c#

#c#

Вопрос:

Нужно ли мне объявлять статический объект и использовать для него блокировку, например

 private static readonly Object padlock = new Object()

public static Test()
{
   lock(padlock) {
          // Blah Blah Blah
   }

}
  

Ответ №1:

(Кстати, ваш код в данный момент не компилировался бы — Readonly должен быть readonly , и вам нужно указать padlock тип.)

Это зависит от того, что вы делаете в методе. Если метод не использует какие-либо общие данные или использует их уже безопасным способом, тогда все в порядке.

Как правило, блокировка требуется только в том случае, если вы обращаетесь к общим данным иным, не потокобезопасным способом. (И весь доступ к этим общим данным должен осуществляться потокобезопасным способом.)

Сказав это, я должен указать, что «потокобезопасность» — довольно расплывчатый термин. У Эрика Липперта есть отличный пост в блоге об этом … вместо того, чтобы пытаться придумать подход «один размер подходит всем», вам следует подумать о том, от чего вы пытаетесь защититься, какие сценарии вы ожидаете и т.д.

Комментарии:

1. Редактирует вопрос для каждого комментария

Ответ №2:

Джон прав; действительно, непонятно, о чем вы здесь спрашиваете. Я бы интерпретировал ваш вопрос так:

Если у меня есть какое-то общее состояние, которое необходимо сделать потокобезопасным путем его блокировки, должен ли я объявить частный статический объект в качестве объекта блокировки?

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

Вы можете подумать, ну, есть много объектов, которые я мог бы использовать. Если объект, который я блокирую, является ссылочным типом, я мог бы его использовать. Или я мог бы использовать объект типа, связанный с содержащим его классом.

Проблема с такими объектами, как блокировки, заключается в том, что становится трудно отследить каждый возможный фрагмент кода, который мог бы использовать объект в качестве блокировки. Поэтому становится трудно анализировать код, чтобы убедиться в отсутствии взаимоблокировок из-за проблем с порядком блокировок. И, следовательно, у вас гораздо больше шансов получить взаимоблокировки. Наличие выделенного объекта блокировки значительно упрощает задачу; вы знаете, что каждое отдельное использование этого объекта предназначено для блокировки, и тогда вы можете понять, что происходит внутри этих блокировок.

Это особенно верно, если у вас когда-либо был ненадежный, враждебный код, запущенный в вашем appdomain. Блокировка объекта типа не требует особых разрешений; что мешает враждебному коду заблокировать все типы и никогда их не разблокировать? Ничего, вот что.