2013-06-29 4 views
1

В ниже код, который я пытаюсь выяснить темы обрабатывать выполнение на синхронизированных блоков:Thread последовательность выполнения синхронизированного блока

public class ThreadExp { 
    public static void main(String[] args) throws InterruptedException { 
     MyRunnable r = new MyRunnable(); 
     Thread t1 = new Thread(r, "Thread1"); 
     Thread t2 = new Thread(r, "Thread2"); 
     t1.start(); 
     t2.start(); 
    } 

} 

class MyRunnable implements Runnable { 

    @Override 
    public void run() { 
     callFn(); 
    } 

    private void callFn() { 
     System.out.println(Thread.currentThread().getName() + ": entered callSync()"); 
     synchronized (Thread.currentThread()) { 
      System.out.println(Thread.currentThread().getName() + ": inside sync"); 
      try { 
       Thread.currentThread().sleep(5000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      System.out.println(Thread.currentThread().getName() + " leaving sync"); 
     } 
     System.out.println(Thread.currentThread().getName() + ": leaving callSync()"); 
    } 
} 

Actual Выход:

Thread1: entered callFn() 
    Thread2: entered callFn() 
    Thread1: inside sync block 
    Thread2: inside sync block 
// 5000 millisec sleep 
    Thread2 leaving sync block 
    Thread1 leaving sync block 
    Thread2: leaving callFn() 
    Thread1: leaving callFn() 

В то время как я ожидал чего-то например:

Thread1: entered callFn() 
Thread2: entered callFn() 
Thread1: inside sync block 
// 5000 millisec sleep 
Thread1 leaving sync block 
Thread1: leaving callFn() 
Thread2: inside sync block 
Thread2 leaving sync block 
Thread2: leaving callFn() 

В целом я думал, что Thread1 приобретет замок, а затем перейдет спать. И только после завершения Thread1 Thread2 может ввести синхронизированный блок.

+0

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

ответ

5

Вы синхронизируете на резьбе:

synchronized (Thread.currentThread()) 

так что каждый поток имеет свой собственный замок, и они могут выполнять synchronized блок одновременно.

Если вы хотите, чтобы блок synchronized работал только по одному потоку за один раз, вам нужно использовать тот же замок.

В вашем примере, это может быть просто this, так как экземпляр Runnable то же самое для двух потоков:

synchronized(this) {...} 

Вывод будет выглядеть следующим образом:

Thread1: entered callSync() 
Thread1: inside sync 
Thread2: entered callSync() 
Thread1 leaving sync 
Thread1: leaving callSync() 
Thread2: inside sync 
Thread2 leaving sync 
Thread2: leaving callSync() 
+0

Синхронизация по Thread.currentThread() кажется совершенно бесполезной - откровенно говоря, кажется ошибкой. Есть ли случай, когда это когда-либо полезно? – user949300

+0

@ user949300 Что он делает, так это создает барьер памяти, но есть намного лучшие способы добиться того же. – assylias

+0

спасибо, что использование этого делает маленький смысл. – user949300

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