Заблокирование каждого объекта выглядит как ошибка дизайна:
- Вы добавляете дополнительную стоимость для каждого созданного объекта, даже если вы фактически используете его только в небольшой части объектов.
- Использование блокировки становится неявным, а
lockMap.get(key).lock()
более читабельным, чем синхронизация на произвольных объектах, напримерsynchronize (key) {...}
. - Синхронизированные методы могут вызывать тонкую ошибку пользователей, блокирующих объект с помощью синхронизированных методов.
- Вы можете быть уверены, что при передаче объекта в третий API-интерфейс parting блокировка не используется.
например,
class Syncer {
synchronized void foo(){}
}
...
Syncer s = new Syncer();
synchronize(s) {
...
}
// in another thread
s.foo() // oops, waiting for previous section, deadlocks potential
- Не говоря уже о разрешении пространства имен для каждого объекта (в С#, по крайней мере, методы статичны, в примитивах синхронизации Java необходимо использовать
await
, а не перегружатьwait
вObject
...)
Однако я уверен, что есть некоторые причины для этого дизайна. Какая большая польза от встроенных замков?