2013-05-10 3 views
1

Привет всем У меня есть этот код:Почему это не синхронизировано правильно?

public class ThreadTester { 
    public static void main(String args[]) { 
     Counter c = new Counter(); 
     for (int i = 0; i < 10; i++) { 
      MyThread a = new MyThread(c); 
      MyThread b = new MyThread(c); 
      a.start(); 
      b.start(); 
     } 
     System.out.println("The value of the balance is " + c.getVal()); 
    } 
} 

class MyThread extends Thread { 
    private Counter c; 
    public MyThread(Counter c){ this.c = c; } 
    public void run(){ s.increment(); } 
} 

class Counter { 
    private int i = 100; 
    public synchronized void increment(){ i++; } 
    public synchronized int getVal(){ return i; } 
} 

Теперь я подумал, что это должно дать желаемый результат 120 - однако результат, кажется, колеблется между 115 и 120. Если бы я добавить Thread.sleep(1) после b.start() я всегда получаю желаемый результат 120. Почему это происходит?

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

ответ

3

Вы печатая значение счетчика после того, начал все темы, а не после того, как все потоки завершили.

Используйте Thread.join() во всех потоках, которые вы начали ждать, пока они не закончили, а затем распечатайте значение. Или используйте CountDownLatch. Сон дает случайный результат. Он позволяет завершить все потоки, но только потому, что у них так мало всего, что спать в течение 1 миллисекунды достаточно.

+0

Редактирование войны для улучшения ответа. Има позволил тебе выиграть со вступлением/защелкой ... ты избил меня до этого :) –

+0

Это не война. Просто хочу дать хороший и полный ответ. –

+0

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

1

Поскольку потоки выполняются параллельно.

Вы печатаете c.getVal() в основном потоке, пока один или несколько других ваших потоков не увеличили его.

Когда вы спите, вы разрешаете другим потокам достаточно времени для завершения, а затем печати.

0

Потому что не все потоки завершили свою задачу приращения к моменту получения System.out. Инъекция сна позволяет завершать потоки перед выходом на выход.

0

Причина:

Третья тема (которая выполняет main()) функция получает следующее заявление сразу после запуска Threads а и Ь в случайном порядке, и именно поэтому вы получите непредсказуемые результаты.

System.out.println("The value of the balance is " + c.getVal()); 

Следующий вопрос:

Если я добавить Thread.sleep (1) после того, как b.start() Я всегда получают желаемый результат 120. Почему это происходит?

Это происходит потому, что вы остановите основной поток достаточно долго (1 секунда - это время в мире процессора), чтобы разрешить Threads a и b.

Решение: Сделайте основной поток до тех пор, пока не будут завершены оба нити a и b. Один из способов:

Counter c = new Counter(); 
    for (int i = 0; i < 10; i++) { 
     MyThread a = new MyThread(c); 
     MyThread b = new MyThread(c); 
     a.start(); 
     b.start(); 
    } 
    a.join(); // wait for thread a to finish 
    b.join(); // wait for thread b to finish 

    System.out.println("The value of the balance is " + c.getVal()); 
0

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

Restructure ваш метод main следующим образом:

public static void main(String args[]) { 
    Counter c = new Counter(); 
    MyThread[] a = MyThread[20]; 
    for (int i = 0; i < 20; i++) { 
     a[i] = new MyThread(c); 
     a[i].start(); 
    } 
    for (int i = 0; i < 20; i++) { 
     a[i].join();   
    } 
    System.out.println("The value of the balance is " + c.getVal()); 
} 

Во-первых, я зацикливание в 20 раз, так как ваш цикл итеративно 10 раз в то время как создание двух потоков (так что вы создавали 20 потоков тоже). Вам нужно удержать ссылки (через массив a), чтобы основной поток мог дождаться завершения всех потоков (с помощью join). Когда все будет завершено, вернется правильный результат.

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