Java два синхронизированных метода в одном экземпляре
рассмотрим следующий код:
public class SynchronizedCounter extends Thread {
private int c = 0;
public synchronized void increment() {
c++;
}
public synchronized void decrement() {
c--;
}
public void run() {
for(;;)
increment();
}
}
static void main(String[] args) {
SynchronizedCounter counter = new SynchronizedCounter();
counter.start();
for(;;)
counter.decrement();
}
означает ли это, что методы increment() и decment() будут ждать друг друга до конца или нет?
EDIT:
и это не ждет?
static void main(String[] args) {
SynchronizedCounter counter1 = new SynchronizedCounter();
SynchronizedCounter counter2 = new SynchronizedCounter();
counter1.start();
for(;;)
counter2.decrement();
}
Ответы
Ответ 1
Да, ключевое слово synchronized
является сокращением для:
synchronized(this) {
//...
}
Таким образом, оба метода эффективно блокируются на одном и том же объекте mutex. Если вы хотите, чтобы они были независимыми друг от друга (что плохой идеей в этом примере, поскольку оба они имеют одинаковое значение), см. Объект блокировки частных членов класса - лучшая практика? (Java).
Кстати, ваш SynchronizedCounter
должен реализовывать Runnable
, а не расширять Thread
, поскольку вы передаете его другому конструктору потока - теперь он немного запутан.
Ответ 2
Блокировка всегда находится на всем объекте. Если какой-либо из них получает доступ к элементам synchronized
.
В вашем первом примере есть два потока , конкурирующих за тот же counter
объект, тот, который вы начали явно (который вызывает метод increment()
в бесконечном цикле), а другой поток основной поток (который бесконечно вызывает decrement()
).
Во втором примере создаются два объекта counter1
и counter2
. Они будут иметь свои собственные блокировки независимо друг от друга. Блокировка одного объекта не влияет на другие потоки от доступа к другому объекту. Два потока (явный и основной поток) получают блокировку на двух разных объектах и, следовательно, в без конкуренции.
Ответ 3
означает ли это, что методы increment() и decment() будут ждать друг друга до конца или нет?
НЕТ, это означает, что ни один другой поток не сможет вызывать increment() и decment(), когда один поток находится внутри них. Чтобы быть полным, другой поток не смог выполнить какой-либо синхронизированный метод этого экземпляра/объекта
Вы можете вызвать любой другой синхронизированный метод из синхронизированного без блокировки на том же экземпляре/объекте