2014-09-18 2 views
1

Я написал программу по синхронизированному блоку, заблокировав на .class, и моя программа выполняет поток по потоку. Но когда я пишу один и тот же код с использованием синхронизированного метода, вывод полностью отличается.Результаты программы с синхронизированной программой отличаются от синхронизированного метода

Синхронного блок программа приведена ниже:

public class SyncBlock { 
    public static void main(String[] args) { 
     final Thread t1 = new SimpleThread("First Thread"); 
     final Thread t2 = new SimpleThread("Second Thread"); 
     t1.start(); 
     t2.start(); 
    } 
} 

class SimpleThread extends Thread { 
    public SimpleThread(String str) { 
     super(str); 
    } 

    public void run() { 
     synchronized (SyncBlock.class) { 
      for (int i = 0; i < 5; i++) { 
       System.out.println(getName() + " says " + i); 
       try { 
        sleep((long) (Math.random() * 1000)); 
       } catch (InterruptedException e) { 
       } 
      } 
      System.out.println(getName() + " is done."); 
     } 
    } 
} 

Выездные путы:

First Thread says 0 
First Thread says 1 
First Thread says 2 
First Thread says 3 
First Thread says 4 
First Thread is done. 
Second Thread says 0 
Second Thread says 1 
Second Thread says 2 
Second Thread says 3 
Second Thread says 4 
Second Thread is done. 

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

Использование синхронизированного метода:

теперь синхронизируются метод запуска и заменить этот код:

public synchronized void run() { 
      for (int i = 0; i < 10; i++) { 
       System.out.println(getName() + " says " + i); 
       try { 
        sleep((long) (Math.random() * 1000)); 
       } catch (InterruptedException e) { 
       } 
      } 
      System.out.println(getName() + " is done."); 
} 

Здесь выход отличается:

First Thread says 0 
Second Thread says 0 
Second Thread says 1 
First Thread says 1 
First Thread says 2 
Second Thread says 2 
First Thread says 3 
Second Thread says 3 
First Thread says 4 
First Thread is done. 
Second Thread says 4 
Second Thread is done. 

ответ

4

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

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

+0

Есть ли какое-либо решение для выполнения по одному потоку с использованием метода синхронизации. – Murali

+0

@Murali - В вашем * конкретном случае, нет. Поскольку ваш код * независим *, вам понадобится блокировка, и вам придется подавать в суд на эту блокировку в обоих местах. Таким образом, для этого потребуется синхронизированный блок, синхронизированный метод не будет работать. Любой метод, который вы синхронизируете, повлияет только на класс (статический метод) или экземпляр (нестатический метод) только класса SimpleThread. – TheLostMind

+1

@ TheLostMind - Спасибо. Таким образом, в синхронном методе мы блокируем поток объектов, но в то же время другой поток объектов также может иметь доступ к методу запуска. это то, что происходит там? – Murali

2

При использовании: synchronized (SyncBlock.class), ваш код работает нормально, потому что вы блокировки в классе SyncBlock, поэтому другой поток не может получить доступ к классу Object SyncBlock, пока не выпустит его первый.

Во втором случае вы блокируете текущий экземпляр SimpleThread (это), блокировка будет отличаться для обоих потоков (вы блокируете сами экземпляры SimpleThread). Таким образом, сам замок находится в эффективной и виртуальная машина, возможно, также удалить код синхронизации (от JDK6 U23 - анализа побега был введен, чтобы оптимизировать такие вещи)

0

В случае синхронизированного блока говорят, первый поток поступает в первый

synchronized (SyncBlock.class) {--> // here First thread takes the lock now no other thread can enter 

Теперь, когда первый поток достигает здесь

System.out.println(getName() + " is done."); 
    } ---> here First thread releases the lock . So this gives chance to other thread which are waiting for this lock . so in ur case Second thread takes it and then executes it and when it reaches here it will release and then again other thread can take over. Note : This behavior is not definite 

Темы могут выполнять любым способом, зависит от политики планирования CPU

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

Также обратите внимание, что sleep не освобождает LOCK.на этом этапе нить находится в состоянии ожидания

+0

Пожалуйста, посмотрите код OPs и ответьте. Хотя первая часть вашего ответа правильная, вторая часть не связана с кодом/вопросом Op. – TheLostMind

0

Ни один из других ответов здесь неверен, но ни один из них не говорит на самом деле.

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

В первом примере метод SimpleThread.run() синхронизируется с уникальным объектом класса SyncBlock. Это предотвращает одновременный ввод обоих потоков в run(), поскольку оба они пытаются синхронизировать один и тот же объект: существует только один объект класса SyncBlock.

В вашем втором примере метод SimpleThread.run() синхронизируется на this. То есть не предотвращает одновременный ввод двух потоков из (2), потому что два потока синхронизируются на двух разных объектах: вы создаете два экземпляра SimpleThread.

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