2010-07-01 4 views
31

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

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

ответ

42

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

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

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

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

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

Состояние резьбы для потока, заблокированного в ожидании блокировки монитора. Нить в заблокированном состоянии ожидает блокировки монитора, чтобы ввести синхронизированный блок/метод или повторно ввести синхронизированный блок/метод после вызова 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 
+0

но если мы сделаем что-то подобное, то что? final Test tt1 = new Test(); final Test tt2 = new Test(); Тема: t1 = new Thread() {public void run() {tt1.m1(); }}; Тема t2 = new Thread() {public void run() {tt2.m2(); }}; – Prem

+0

Я запускаю то же самое, и я получил TIMED_WAIT как результат .... – Prem

+0

@aioobe что происходит в случае синхронизированных блоков кода (а не методов). может ли два потока получить доступ к двум различным синхронизированным кодовым блокам одного и того же объекта одновременно? – yuva

11

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

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

+0

Фактически, он будет находиться в состоянии BLOCKED, а не в состоянии WAITING. – aioobe

+0

Вызов 'a2.m2()' в приведенном выше примере немного вводит в заблуждение. Поскольку 'a1' и' a2' - это разные экземпляры класса 'A', каждый имеет свой собственный' lock'. Поэтому даже 'a1.m1()' и 'a2.m1()' могут выполняться одновременно. – derenio

+0

@derenio - это был весь момент, который я делал в этом разделе, на основе смелого заявления, предшествующего этому. И так как вопрос задается вопросом о том, можно ли сразу вызвать m1 и 'm2', это то, что я придерживался в этом примере. –

4

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

1

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

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

Замки В synchronized Методы

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

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

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

Если нет, то было бы состояние t2?

Резьба t2 находится в заблокированном состоянии и ждет потока t1, чтобы освободить замок.

С JAVA documentation страницы:

решений synchronized метод имеет два эффекта.

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

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

Смежные вопросы