Сделайте два синхронизированных метода выполняются одновременно

У меня есть 4 метода (m1, m2, m3 и m4) в классе. Метод m1, m2 и m3 synchronized методы. Кроме того, у меня есть 4 потока t1, t2, t3 и t4 соответственно.

Если t1 получите доступ m1 метод (синхронизированный метод), мог t2 доступ потока m2 метод (синхронизированный метод) одновременно? Если не, каково было бы состояние t2?

32
задан Shashank Agrawal 17 February 2016 в 13:25
поделиться

3 ответа

Если 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
45
ответ дан 27 November 2019 в 20:34
поделиться

Если методы синхронизируются на одном мониторе, они не могут выполняться одновременно в разных потоках. Когда второй поток доходит до записи монитора (в данном случае запуск синхронизированного метода), он блокируется до тех пор, пока первый поток не освободит монитор.

Фактическое состояние заблокированного потока в этом случае, как сообщает 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 вызовы методов экземпляра.

11
ответ дан 27 November 2019 в 20:34
поделиться

Нет, не мог. Это единственный момент synchronized: разные потоки не могут делать эти вещи одновременно (вам не нужно защищаться от того, что один и тот же поток делает их одновременно, потому что один поток вообще не может делать что-либо параллельно). Состояние ожидающего потока — «ожидание блокировки». (С достаточно современной JVM вы действительно можете отобразить это состояние на консоли, если вы спросите правильным образом.)

4
ответ дан 27 November 2019 в 20:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: