2013-09-24 2 views
0

Iam new для синхронизации и многопоточности, пожалуйста, ответьте, почему этот код не получает блокировку объекта b.Почему не синхронизированный метод вызывается при покупке блокировки объекта?

public class Tetsclass { 

    public static void main(String[] args) { 
     B b = new B(); 
     A a = new A(b); 
     A2 a2 = new A2(b); 
     Thread t1= new Thread(a); 
     Thread t2= new Thread(a2); 
     t1.start(); 
     try { 
      Thread.sleep(2000); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     t2.start(); 
    } 
} 
class B { 
    public synchronized void waitfor() {   
     synchronized (B.class) { 
      System.out.println("Lock aquired on "+System.currentTimeMillis()); 
      try { 
       Thread.sleep(5000); 
      } catch (InterruptedException e) {  
       e.printStackTrace(); 
      } 
      System.out.println("Lock released"); 
     } 

    } 
    public void readObject() { 
     System.out.println("readobject by thread==="+Thread.currentThread().getName()+" on "+System.currentTimeMillis()); 

    } 
} 
class A2 implements Runnable { 

    B b=null; 
    public A2(B b) { 
     this.b = b; 
    } 

    @Override 
    public void run() {  
     b.readObject();  
    } 
} 
class A implements Runnable { 

    B b=null; 
    public A(B b) { 
     this.b = b; 
    } 
    @Override 
    public void run() {    
     b.waitfor();     
    } 
} 

Я ожидал, что выход:

Lock aquired on 1380016080337 
Lock released 
readobject by thread===Thread-1 on 1380016082337 

но вывод:

Lock aquired on 1380016080337 
readobject by thread===Thread-1 on 1380016082337 
Lock released 

ответ

4

readObject метод, в том числе его вызова из A2#run, не предполагает приобретения замка. Поэтому фиксация вашей другой нити не имеет отношения к выполнению readObject.

Видимо, у вас есть непонимание семантики замков. Вы считаете, что когда вы блокируете B.class, вы заблокировали «весь класс». Состояние дел совершенно иное: B.class - это еще один объект, и все объекты имеют связанный с ним монитор, который может быть получен потоком. Взаимное исключение происходит только между потоками, которые утверждают, что приобретают один и тот же замок. Не существует семантических отношений между объектом как блокировкой и любым из его методов, а одно и то же - для объектов класса vz. экземпляры этого класса.

Одним из способов вашего недоразумения могло возникнуть это с помощью объектов, используемых неявно synchronized методов: синхронизированный метод экземпляра приобретает this как замок, в то время как синхронизированный статический метод получает блокировку на соответствующем объекте класса.

+0

да, но при вызове синхронного метода он получит блокировку для всего объекта. Итак, почему этот readObject вызывается? – Achyut

+0

Вы уверены, что прочитали мой ответ в полном объеме? В моем втором и третьем абзацах подробно рассмотрен ваш вопрос. –

0

Поскольку readObject() не требует приобретения замка, он не будет ждать, пока другой поток освободит замок. Эта путаница может возникнуть из-за Thread.sleep(2000), который у вас есть в вашем тестовом классе.

Попробуйте изменить это на Thread.sleep(10000) и посмотреть выход. Вы получите желаемый результат.

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

Во втором случае A2 нить будет ждать 10 секунд после A начинается, и в этих 10 секунд, ваш A начнет, сон 5 секунд и освободить замок, после чего ваш A2 будет выполнен без каких-либо задержек.

2

Его поведение, как ожидалось. Вот что происходит на линии времени

a - звонки ждать (который спит 5 секунд перед тем как отпустить замок) a2 - вызовы чтения, который печатает прочитать сообщение.

  t   t+dt             t+dt+5 
---------|-----------|--------------------------------|--------------------------|---------- 
     [a starts] [print(lock acquired)]    [sleeps(5)]   [print(lock released)] 
          t+2 
----------------------------|--------------|--------------------------|-------------- 
         [a2 starts] [print(read message)] 

Там нет блокировка любого вида в вашем readObject()

0

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

class B { 
    public synchronized void waitfor() {   
     synchronized (B.class) { 
      System.out.println("Lock aquired on "+System.currentTimeMillis()); 
      try { 
       Thread.sleep(5000); 
      } catch (InterruptedException e) {  
       e.printStackTrace(); 
      } 
      System.out.println("Lock released"); 
     } 

    } 
    public void readObject() { 
     synchronized(B.class) 
     { 
     System.out.println("readobject by thread==="+Thread.currentThread().getName()+" on "+System.currentTimeMillis()); 
     } 
    } 
} 
Смежные вопросы