Поток безопасности объекта - статический или нет? - PullRequest
11 голосов
/ 23 апреля 2009

Я недавно был на собеседовании, и технический специалист спросил меня, как сделать приложение поточно-ориентированным.

Хорошо, после правильного объяснения lock(), он сказал, что не стоит иметь объект как статический.

private static readonly object _syncLock = new object();

Он утверждал, что причина в том, что static делает этот объект медленнее для блокировки потоков, чем если бы он не был статичным. Это правда?

EDIT: Тем не менее я все еще не уверен. В чем разница между этими тремя подходами?

private static readonly object _syncLock = new object();
public static readonly object _syncLock = new object();
private readonly object _syncLock = new object();

Ответы [ 6 ]

12 голосов
/ 23 апреля 2009

Если объект блокировки должен быть статическим или нет, зависит от объекта, который вы хотите заблокировать. Если вы хотите заблокировать экземпляр класса, вы не можете использовать объект статической блокировки. Если вы хотите заблокировать статические данные, вы не можете использовать объект блокировки экземпляра. Так что, похоже, выбора нет.

Можно подумать об использовании статического объекта или объекта блокировки экземпляра для блокировки доступа к данным экземпляра, но это приводит к другому поведению. С объектом блокировки экземпляра вы блокируете только экземпляр, в то время как статический объект блокировки блокирует все экземпляры. Так что здесь тоже нет выбора для настройки производительности.

7 голосов
/ 23 апреля 2009

Он заявил, что причина в том, что static запускается во время выполнения вместо компиляции и замедляет блокировку этого объекта, чем если бы он не был статичным.

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

0 голосов
/ 15 июня 2011

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

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

0 голосов
/ 23 апреля 2009

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

Допустим, у вас есть несколько классов List со специальным методом Reorder, который принимает некоторые странные аргументы. Подумайте, нужно ли вам переупорядочивать 100 разных списков во время каких-либо параллельных процессов. Вам важно только, чтобы разные потоки не манипулировали одним и тем же списком в одно и то же время, так как это может повлиять на логику переупорядочения. Вам не нужна статическая блокировка, так как вам все равно, когда одновременно обрабатываются разные списки.

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

0 голосов
/ 23 апреля 2009

Остальные верны, что выбор использования статического поля экземпляра зависит от того, какое состояние (на уровне класса или на уровне экземпляра) вам необходимо заблокировать, и нет существенной разницы в скорости для самой блокировки. НО если вам действительно нужно использовать только данные экземпляра, тогда ваше приложение может работать намного быстрее, используя lock(this), вместо того, чтобы блокировать все потоки от доступа к данным ЛЮБОГО экземпляра. Это могло быть тем, к чему стремился интервьюер - в приложении, где несколько потоков используют только данные экземпляра, он действительно должен работать быстрее, если вы заблокируете экземпляр только потому, что он не будет блокировать использование другими экземплярами других потоков.

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

[Редактировать - в конце концов, это не очень хорошая идея, см. Комментарии ниже]

lock(typeof(MyClass))
{
  // use class-level data
}

Это исключает необходимость создания поля статического объекта.

0 голосов
/ 23 апреля 2009

Иногда на собеседовании я говорю что-то, что, как я знаю, неверно или что-то совершенно бессмысленное, чтобы увидеть, будет ли кандидат эффективно отстаивать свою точку зрения или просто сдастся и согласится.

О, а вот отличная статья Джеффри Рихтера о правильном использовании блокировки. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...