Так что synchronized
всегда нужен объект для работы.Все synchronized
блоки, которые совместно используют один и тот же объект, являются взаимоисключающими (т.е. только один поток может войти в блок за один раз).Помещение synchronized
в объявление метода - это сокращение, например, методы равны synchronized(this)
, а статические методы - synchronized(Foo.class)
(где Foo
- класс, содержащий статический метод).
Зная этоВы можете легко создать несколько объектов для синхронизации, контролируя, какие методы могут быть запущены одновременно, а какие нет.
Пример класса, который позволяет запускать method3 одновременно с method1 или method2,но method1 и method2 являются взаимоисключающими.Кроме того, только один поток может запускать каждый метод одновременно.
public class Foo {
private final static Object lock1 = new Object();
private final static Object lock2 = new Object();
public static void method1() {
synchronized(lock1) {
...
}
}
public static void method2() {
synchronized(lock1) {
...
}
}
public static void method3() {
synchronized(lock2) {
...
}
}
}
Обратите также внимание на статический и нестатический.Здесь методы статические, а блокировки статические, так что все хорошо.Если бы методы были нестатичными, это предотвратило бы вызов методов также для разных объектов, это может быть не то, что вам нужно.В этом случае если сделать блокировки нестатичными, каждый экземпляр Foo
будет работать, как описано ранее, но в случае foo1.method1()
и foo2.method2()
блокировки не будет, поскольку они не будут синхронизироваться на одном и том же объекте..
Как показывает ответ Шубхам Кадлаг, synchronized
далеко не единственный инструмент параллелизма, который есть в Java.Пакет java.util.concurrent.locks
имеет классы для блокировки (тогда как synchronized
является встроенным механизмом).Например, ReentrantReadWriteLock
позволяет вам обрабатывать ситуации, когда несколько потоков могут что-то делать (читать) одновременно, но только одному потоку разрешено выполнять операцию модификации (записи) одновременно.Они также позволяют вам установить тайм-аут на блокировку, тогда как synchronized
будет радостно ждать вечно (не то, что tryLock()
часто требуется, так как это ошибка программирования, если вы получаете взаимоблокировки).
Тогда выпоймите, что ручная блокировка для чурбанов в любом случае, и обнаружите, что java.util.concurrent
имеет много классов, которые скрывают от вас блокировку и предлагают всевозможные расширенные функциональные возможности.