2013-12-03 5 views
1

Я пытаюсь синхронизировать приложение потока с использованием синхронизированного ключевого слова. Иногда это странно. Существует двусмысленность в размещении ключевого слова synchronized. Код выглядит следующим образом:Синхронизация потоков Java - размещение синхронизированного ключевого слова

class Athread implements Runnable 
{ 
    public void run() { 

      System.out.println("Starting Implementation of Class Athread"); 
      for(int i=1;i<=10;i++) 
      { 
       System.out.println("Class Athread :"+i); 
      } 
      System.out.println("Ending Implementation of class Athread"); 
    } 
} 

class Bthread implements Runnable 
{ 
    public void run() { 

      System.out.println("Starting Implementation of Class Bthread"); 
      for(int i=11;i<=20;i++) 
      { 
       System.out.println("Class Bthread :"+i); 
      } 
      System.out.println("Ending Implementation of class Bthread"); 
    } 
} 

public class ThreadDemo { 
    public static void main(String[] args) { 
     System.out.println("Program starts.."); 

     Athread t1 = new Athread(); 
     Thread th1 = new Thread(t1); 


     Bthread t2 = new Bthread(); 
     Thread th2 = new Thread(t2); 

     synchronized(th1){ 
      th1.start(); 
     } 
     synchronized(th2){ 
      th2.start(); 
     } 

     System.out.println("Program ends..."); 
    } 
} 

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

Program starts.. 
Program ends... 
Starting Implementation of Class Athread 
Starting Implementation of Class Bthread 
Class Athread :1 
Class Bthread :11 
Class Athread :2 
Class Bthread :12 
Class Athread :3 
Class Bthread :13 
Class Athread :4 
Class Bthread :14 
Class Athread :5 
Class Bthread :15 
Class Athread :6 
Class Bthread :16 
Class Athread :7 
Class Bthread :17 
Class Athread :8 
Class Bthread :18 
Class Athread :9 
Class Bthread :19 
Class Athread :10 
Class Bthread :20 
Ending Implementation of class Athread 
Ending Implementation of class Bthread 

Даже когда я использую синхронизированную ключевое слово в методе Run() из обоих класса я не получить фактический желаемый результат.

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

Спасибо.

ОБНОВЛЕНИЕ:

В вопросе выше, я неправильно понял концепцию синхронизации. В соответствии с полученными комментариями я пытаюсь позвонить двух разных потоков и получить доступ к двум различным ресурсам. Но синхронизация должна выполняться на общем/общем ресурсе. Следовательно, должно быть общее местоположение, на котором я должен попытаться синхронизировать.

+0

Как вы думаете, что «синхронизировано»? –

+0

Он контролирует доступ к потоку поверх других потоков. Короче говоря, «только по одному потоку за раз» – Neal

+0

И что он делает с аргументом, который вы передаете ему? И как это связано с другим аргументом, который вы передаете другому «синхронизированному» блоку? –

ответ

2

Что вы сделали, вы синхронизировали фрагмент кода, в котором начинается ваша нить. И в это время выполняется только основной метод, поэтому при установке синхронизированного блока вы ничего не достигли.

Во-вторых, вы создаете 2 потока на 2 разных объектах, поэтому ни один из потоков не мешает друг другу, поэтому установка синхронизированного блока в запуске или синхронизация метода запуска не будет делать ничего другого.

Я не знаю, чего именно вы хотите достичь, но я изменил ваш код для «синхронизированного» примера.

class MyClass implements Runnable{ 
    public void run() { 
      System.out.println(this); 
      System.out.println("Starting Implementation of "+Thread.currentThread().getName()); 
      synchronized(this){ 
       for(int i=1;i<=10;i++){ 
        System.out.println("Class :"+Thread.currentThread().getName()+" "+i); 
       } 
      } 
      System.out.println("Ending Implementation of "+Thread.currentThread().getName()); 
    } 
} 


public class ThreadDemo { 
    public static void main(String[] args) { 
     System.out.println("Program starts.."); 

     MyClass obj = new MyClass(); 
     Thread th1 = new Thread(obj); 
     Thread th2 = new Thread(obj); 
     th1.setName("Athread"); 
     th2.setName("BThread"); 
     th1.start(); 
     th2.start(); 

     System.out.println("Program ends..."); 
    } 
} 
+0

Я не думаю, что этот код работает, так как «это», на котором вы синхронизированы, отличается для двух потоков. Как быстрое (слегка уродливое) исправление, синхронизируйтесь на MyClass.class. – user949300

+0

для обоих потоков «это» означает тот же объект. см. строку «Thread th1 = new Thread (obj);» и 'Thread th2 = new Thread (obj);' – Aniruddha

+0

Для одного из них это th1, для другого th2. – user949300

1

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

Теперь, во-первых, вы создаете темы из двух разных классов, не знаете, почему вы это делаете здесь. Во-вторых, вы не используете какой-либо ресурс в классах для синхронизации.

В-третьих, используйте синхронизацию внутри класса, который вы создаете.

+0

Не могли бы вы объяснить мне пример. Это было бы более ясно. – Neal

0

Я не уверен, что если его правильно положить синхронизированный блок в бегах() метод обычно синхронизируется объявлен в определенном методе пользователя для метода ex.business ..

, а также почему используя ту же переменную «i» в ваших циклах? может также вызвать некоторые проблемы с природой значений.

+0

'i' - локальная переменная, которая не видна вне метода' run' - эта часть полностью безопасна, потому что два 'i' являются разными. – zapl

0

если на желаемый результат вы имеете в виду, что Athread shoudl закончить до того Bthread начинается тогда ваш выбор синхронизации является неправильным.

Синхронизировать имеет 2 thinsg, чтобы понять:

  1. нити блокируют друг друга, если синхронизация на тот же объект
  2. нитей работает в синхронном блоке на разные объекты Dont блокируют друг друга.

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

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

Object lockObject = new Object(); 

class Athread implements Runnable 
{ 
    public void run() { 
     synchronized(lockObject){ 
      System.out.println("Starting Implementation of Class Athread"); 
      for(int i=1;i<=10;i++) 
      { 
       System.out.println("Class Athread :"+i); 
      } 
      System.out.println("Ending Implementation of class Athread"); 
     } 
    } 
} 

class Bthread implements Runnable 
{ 
    public void run() { 
     synchronized(lockObject){ 
      System.out.println("Starting Implementation of Class Bthread "); 
      for(int i=1;i<=10;i++) 
      { 
       System.out.println("Class Bthread :"+i); 
      } 
      System.out.println("Ending Implementation of class Bthread "); 
     } 
    } 
} 

Вместо synchronized(lockObject) вы можете также использовать synchronized(ThreadDemo.class). Идея состоит в том, что синхронизированные блоки bpoth должны синхронизироваться на одном и том же объекте. Это оно.

0

synchronized(foo) { do stuff } означает, что, пока вы делаете вещи, у вас есть эксклюзивный доступ к объекту foo. И вы готовы подождать. Хорошим примером может служить банковский счет. Пока я делаю депозит до , мой банковский счет, никто другой не может получить к нему доступ. Тем не менее, еще один поток прекрасно может синхронизировать и получать ваш банковский счет, или мой счет сбережения.

В вашем примере вам нужен общий объект для обоих потоков, чтобы «сражаться». Одним из решений является просто создание третьего объекта (не нулевого!) Любого типа. Скажите static Object lockOnMe = new Object();.

Однако, поскольку вы действительно хотите получить эксклюзивный доступ к System.out, это было бы более логичным выбором. Хотя AThread или BThread запущены, если они синхронизируются в System.out в методе run(), никто другой не может получить доступ к System.out и помешать вашему хорошему выводу.

Теперь в «реальном» приложении есть недостатки, так как многие потоки могут застревать в ожидании печати, это работает для примера обучения.

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