У меня есть 4 метода (m1
, m2
, m3
и m4
) в классе. Метод m1
, m2
и m3
synchronized
методы. Кроме того, у меня есть 4 потока t1
, t2
, t3
и t4
соответственно.
Если t1
получите доступ m1
метод (синхронизированный метод), мог t2
доступ потока m2
метод (синхронизированный метод) одновременно? Если не, каково было бы состояние t2?
Если t1 обращается к методу m1 (синхронизированный метод), может ли поток t2 обращаться к методу m2 (синхронизированный метод) одновременно?
Ключевое слово synchronized
применяется к уровень объекта , и только один поток может удерживать блокировку объекта. Итак, пока вы говорите об одном и том же объекте, тогда no , t2
будет ждать, пока t1
снимет блокировку, полученную при входе в m1
.
Однако поток может снять блокировку без возврата из метода, вызвав Object.wait ()
.
Если нет, в каком состоянии будет t2?
Он будет сидеть и ждать, пока t1
освободит блокировку (возврат из метода или вызов Object.wait ()
). В частности, он будет в состоянии ЗАБЛОКИРОВАНО
.
Состояние потока для потока, заблокированного в ожидании блокировки монитора. Поток в заблокированном состоянии ожидает блокировки монитора для входа в синхронизированный блок / метод или повторного входа в синхронизированный блок / метод после вызова
Object.wait
.
Пример кода:
public class Test {
public synchronized void m1() {
try { Thread.sleep(2000); }
catch (InterruptedException ie) {}
}
public synchronized void m2() {
try { Thread.sleep(2000); }
catch (InterruptedException ie) {}
}
public static void main(String[] args) throws InterruptedException {
final Test t = new Test();
Thread t1 = new Thread() { public void run() { t.m1(); } };
Thread t2 = new Thread() { public void run() { t.m2(); } };
t1.start();
Thread.sleep(500);
t2.start();
Thread.sleep(500);
System.out.println(t2.getState());
}
}
Вывод:
BLOCKED
Если методы синхронизируются на одном мониторе, они не могут выполняться одновременно в разных потоках. Когда второй поток доходит до записи монитора (в данном случае запуск синхронизированного метода), он блокируется до тех пор, пока первый поток не освободит монитор.
Фактическое состояние заблокированного потока в этом случае, как сообщает jconsole, будет примерно таким же, как java.lang.Thread.Состояние: WAITING (на мониторе объекта)
Предполагая, что все методы являются обычными методами экземпляра, тогда они будут использовать один и тот же монитор при вызове для одного и того же объекта . То есть, если у вас было что-то вроде:
// Thread 1
A a1 = new A();
a1.m1();
// Thread 2
A a2 = new A();
a2.m2()
, то в этом случае второй поток сможет вызвать метод, потому что он пытается получить неявный монитор объекта a2
, которым является не заблокирован потоком 1. Но если поток 2 попытается вызвать a1.m2 ()
, то он заблокируется, пока поток 1 не завершит выполнение m1 ()
.
Если у вас есть статические методы, они получают явный монитор самого класса ( A.class
в моем случае с гипотетическим именованием), поэтому не будут заблокированы any вызовы методов экземпляра.
Нет, не мог. Это единственный момент synchronized
: разные потоки не могут делать эти вещи одновременно (вам не нужно защищаться от того, что один и тот же поток делает их одновременно, потому что один поток вообще не может делать что-либо параллельно). Состояние ожидающего потока — «ожидание блокировки». (С достаточно современной JVM вы действительно можете отобразить это состояние на консоли, если вы спросите правильным образом.)