Разница между блокировкой (этой) и блокировкой на статическом объекте - PullRequest
11 голосов
/ 31 июля 2011

Какой из следующих двух фрагментов кода лучше использовать?

static readonly object _locker = new object();
lock (_locker)

или

lock (this)

this является объектом текущего экземпляра. Так почему же lock (_locker) всегда в книгах?

Связанный:
В чем разница между блокировкой (this) и блокировкой (thisLock)?
Почему блокировка (это) {& hellip;} плохая?

Ответы [ 3 ]

20 голосов
/ 31 июля 2011

Там может быть большая разница.Самое большое различие между ними состоит в том, что в первом примере для блокировки используется один объект (отсюда и ключевое слово static), а во втором примере ключевое слово this подразумевает блокировку экземпляра.Следовательно, с точки зрения производительности и даже с точки зрения корректности может быть большая разница, но это зависит от кода внутри блокировки.

Когда все, что вам нужно, - это синхронизировать доступ к полям уровня экземпляра, вы не должныиспользуйте ключевое слово static, поскольку оно будет синхронизировать сам код, а не данные (что может привести к ненужному снижению производительности).Конечно, если сами данные являются статическими (данные уровня класса вместо данных уровня экземпляра), вам нужно использовать ключевое слово static.С другой стороны, когда вы используете ключевое слово this для блокировки, когда вы получаете доступ к общим / статическим ресурсам, у вас (конечно) будет проблема с корректностью, поскольку синхронизация происходит на основе экземпляра, а несколько экземпляров по-прежнему будутвозможность доступа к общим данным одновременно.

И есть еще одна проблема, но разница намного меньше, чем для ранее отмеченных отличий.В первом примере для блокировки используется закрытый объект, а во втором - указатель this, который является ссылкой на объект самого метода этого экземпляра.Поскольку эта ссылка общедоступна для других объектов, они могут заблокировать ее, что в редких случаях может привести к взаимоблокировке.Если вы разработчик приложений, я бы не стал сильно беспокоиться об этом (если вы не пользуетесь такими вещами, как System.String или System.Type), но если вы являетесь разработчиком фреймворка, вам определенно не следуетиспользуйте lock(this), поскольку невозможно определить, каким образом разработчики приложений будут (ab) использовать ваш код.

8 голосов
/ 31 июля 2011

Почти всегда предпочтительнее заблокировать закрытый объект только для чтения.

Разница в том, что this обычно виден внешнему коду, который может блокировать его, т. Е. -

var obj = new YourClass();
lock(obj)
{
    ...
}

... в этом случае любая попытка внутри YourClass до lock (this) заблокирует.

1 голос
/ 31 июля 2011

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

Если вы используете блокировку (это), вы можете получить тупик:

void blah() {
   lock(this);
   sleep(200);
}

//Some other block of code

MyObject a;
foreach(Mythread m in threads)
{
   lock(a);
   m.Call(a.blah); //Not the best syntax, but you get the idea.
}

Если вы удерживаете замок внутри объекта, он не заходит в тупик.

...