В примере methodA и methodB - это методы экземпляра (в отличие от статических методов). Помещение synchronized
в метод экземпляра означает, что поток должен получить блокировку (внутреннюю блокировку) на экземпляре объекта, для которого вызывается метод, прежде чем поток сможет начать выполнение любого кода в этом методе.
Если у вас есть два разных метода экземпляра, помеченных как синхронизированные, и разные потоки одновременно вызывают эти методы для одного и того же объекта, эти потоки будут бороться за одну и ту же блокировку. Как только один поток получает блокировку, все другие потоки закрываются для всех синхронизированных методов экземпляра этого объекта.
Чтобы два метода работали одновременно, им пришлось бы использовать разные блокировки, например:
class A {
private final Object lockA = new Object();
private final Object lockB = new Object();
public void methodA() {
synchronized(lockA) {
//method A
}
}
public void methodB() {
synchronized(lockB) {
//method B
}
}
}
где синтаксис синхронизированного блока позволяет указать конкретный объект, который исполняющему потоку необходимо получить внутреннюю блокировку, чтобы войти в блок.
Важно понимать, что даже несмотря на то, что мы помещаем ключевое слово synchronized в отдельные методы, основная концепция заключается в скрытой внутренней блокировке.
Вот как руководство по Java описывает отношения:
Синхронизация строится вокруг внутренней сущности, известной как внутренняя блокировка или блокировка монитора. (Спецификация API часто называет этот объект просто монитором.) Внутренние блокировки играют роль в обоих аспектах синхронизации: обеспечение монопольного доступа к состоянию объекта и установление отношений «происходит раньше», которые необходимы для видимости.
С каждым объектом связана внутренняя блокировка. По соглашению поток, которому требуется монопольный и согласованный доступ к полям объекта, должен получить внутреннюю блокировку объекта перед доступом к ним, а затем освободить внутреннюю блокировку, когда это будет сделано с ними. Говорят, что поток владеет внутренней блокировкой между моментом, когда он получил блокировку и снял блокировку. Пока поток владеет внутренней блокировкой, никакой другой поток не может получить такую же блокировку. Другой поток заблокируется, когда попытается получить блокировку.
Блокировка предназначена для защиты общих данных. Вы должны использовать отдельные блокировки, как показано в приведенном выше примере кода, только если каждая блокировка защищает разные элементы данных.
person
Nathan Hughes
schedule
15.03.2013