Подходит ли 'lock (this)' для синхронизации каждой функции-члена? - PullRequest
1 голос
/ 16 января 2011

У меня есть класс Singleton, который сильно зависит от файла XML, который он использует в качестве базы данных.В конструкторе файл XML читается, а FileSystemWatcher ожидает дальнейших изменений.

Теперь, если произойдут какие-либо изменения, я снова буду читать данные из файла XML, но на этом этапеФункции класса должны быть доступны до тех пор, пока файл XML не будет перезагружен.

Мой вопрос: можно ли просто использовать this в качестве объекта синхронизации (при перезагрузке файла XML) и не вносить никаких изменений в функции?поставить большой lock на каждую функцию?

Ответы [ 3 ]

5 голосов
/ 16 января 2011

Не lock на this. Когда-либо. Это потому, что код, который вы не можете контролировать, может заблокировать ваш объект и привести к очень трудному обнаружению сценария взаимоблокировки.

Вместо этого используйте выделенный lock объект:

private readonly object locker = new object();

Тогда:

lock(locker) {
   // something something
}

Поскольку locker помечен как private, вам не нужно беспокоиться о коде, внешнем по отношению к вашему объекту, блокирующем ваш объект.

5 голосов
/ 16 января 2011

lock(this) лучше избегать - существует крайний случай, когда какой-то другой не связанный код может также заблокировать его, что может даже вызвать тупик.

Лучший подход:

private readonly object lockObj = new object();

А потом lock(lockObj) - поскольку это личное, вы избегаете этого крайнего случая.

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

private SomeModel model;
public void Refresh() {
     SomeModel newModel = new ...
     // fully load etc
     ...
     model = newModel;
}

Это лучше всего работает, если вы всегда делаете снимок, т.е. вместо

var foo = model.Foo;
var bar = model.Bar;

Вы используете:

var snapshot = model;
var foo = snapshot.Foo;
var bar = snapshot.Bar;

Теперь мы знаем, что Foo и Bar принадлежат к одной модели.

0 голосов
/ 16 января 2011

Если наблюдатель является единственным автором, а ваши объекты - только читателями, ReaderWriterLock может быть лучше.Обязательно ознакомьтесь с разделом замечаний.

...