Плюсы и минусы обоих
Первый вариант плюсы: позволяет блокировать концепцию, а не объекты.Если бы вам пришлось заблокировать несколько ресурсов для одного действия (которое обычно не рекомендуется, но иногда необходимо), вы могли бы сделать это с гораздо меньшим беспокойством о состоянии гонки.
cons: объект все еще можно изменить,поэтому вам нужно убедиться, что доступ к объекту ограничен методами, которые соблюдают внешнюю блокировку.
Второй вариант плюсы: блокировка на объекте должна помешать другим изменять его (хотя вы должны дважды проверить точную симантику.) РЕДАКТИРОВАТЬ: имеет тот же кон, что и выше - если методы не synchronized
внутренне, вы все равно можете столкнуться с методами, которые не соблюдают контракт.
cons: Вы блокируете доступ ко всем методамдаже те, которые не связаны с тем, что вы пытаетесь использовать, что может привести к замедлению и, возможно, к тупику.Однако вы могли бы легко доказать, что в этом случае ваш объект выполняет слишком много работы и должен быть разбит.
РЕДАКТИРОВАТЬ: Позвольте мне пояснить часть 2 здесь (случай разбить MyType наMyFoo и MyBar открыты для обсуждения ...)
class MyType {
Foo foo;
Bar bar;
void doFoo() { foo.do(); }
void doBar() { bar.do(); }
}
class MyActions {
MyType thing;
void lotsOfFoo() {
// blocks bar :-(
synchronized(thing) { thing.doFoo(); }
}
void lotsOfBar() {
// blocks foo :-(
synchronized(thing) { thing.doBar(); }
}
}
Лично я использую вариант 1 гораздо чаще (поэтому я не уверен насчет этой части в варианте 2).