Два синхронизированных метода выполняются одновременно - PullRequest
31 голосов
/ 01 июля 2010

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

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

Ответы [ 4 ]

44 голосов
/ 01 июля 2010

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

Ключевое слово synchronized применяется к уровню объекта , и только один поток может удерживать блокировку объекта. Поэтому, пока вы говорите об одном и том же объекте, no , t2 будет ожидать, пока t1 не снимет блокировку, полученную при вводе m1.

Тем не менее, поток может снять блокировку, не возвращаясь из метода, вызвав Object.wait().

Если нет, каково будет состояние t2?

Он будет сидеть и ждать, пока t1 снимет блокировку (вернитесь из метода или вызовите Object.wait()). В частности, он будет в состоянии BLOCKED .

Состояние потока для потока, заблокированного в ожидании блокировки монитора. Поток в заблокированном состоянии ожидает блокировки монитора для ввода синхронизированного блока / метода или повторного входа в синхронизированный блок / метод после вызова 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
11 голосов
/ 01 июля 2010

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

Фактическое состояние заблокированного потока в этом случае, так какjconsole сообщает что-то вроде java.lang.Thread.State: WAITING (on object monitor)

Если все методы являются обычными методами экземпляра, то они будут использовать один и тот же монитор при вызове для одного и того же объекта .То есть, если у вас было что-то вроде:

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

4 голосов
/ 01 июля 2010

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

1 голос
/ 17 февраля 2016

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

Нет. Поток t2 будет ожидать, пока поток t1 освободит блокировку. В том же примере t2 может получить доступ к методу m4, который не синхронизирован.

Locks In синхронизировано Методы

С каждым объектом связан внутренний замок. По соглашению поток, которому требуется исключительный и согласованный доступ к полям объекта, должен получить внутреннюю блокировку объекта перед тем, как получить к ним доступ, а затем снять внутреннюю блокировку, когда это будет сделано с ними

Когда поток вызывает синхронизированный метод, он автоматически получает встроенную блокировку для объекта этого метода и освобождает ее при возврате метода. Снятие блокировки происходит, даже если возврат был вызван необработанным исключением

Возвращаясь ко второму запросу:

Если нет, то в каком состоянии находится t2?

Поток t2 находится в заблокированном состоянии и ожидает, пока Поток t1 снимет блокировку.

Из Java Документация Страница:

метод synchronized имеет два эффекта.

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

Во-вторых, при выходе из синхронизированного метода он автоматически устанавливает отношение «до и после» с любым последующим вызовом синхронизированного метода для того же объекта. Это гарантирует, что изменения состояния объекта видны всем потокам

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...