2016-12-03 5 views
-1
public class RunTest { 
    public static int counter = 0; 
    static class RunnerDec implements Runnable{ 
     public void run(){ 
      for(int i=0;i<5000; i++){ 
       counter--; 
      } 
     } 
    } 

    static class RunnerInc implements Runnable{ 
     public void run(){ 
      for(int i=0;i<5000; i++){ 
       counter++; 
      } 
     } 
    } 

    public static void main(String[] args) { 
     RunnerDec rd = new RunnerDec(); 
     RunnerInc ri = new RunnerInc(); 
     Thread t1 = new Thread(rd); 
     Thread t2 = new Thread(ri); 
     t1.start();  
     t2.start(); 
     try{ 
      t1.join(); // this will stop the main thread until t1 is done incrementing 5000 times 
      t2.join(); // this will stop the main thread until t2 is done incrementing 5000 times 
     }catch(Exception e){ 
      e.printStackTrace(); 
     } 
     System.out.println(counter); 
    } 

} 

Я ожидаю, что результат будет 0 каждый раз, увы, это не так. В java-документе говорится, что join() «ожидает, что этот поток умрет». Я чувствую, что основной поток должен ждать окончания t1, а затем ждать окончания t2. Это не то, что происходит. Спасибо за ясность!Java Thread присоединиться() поведение

+0

Как вы думаете, «начало»? –

ответ

2

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

Например:

counter = 1000 
thread 1 reads counter : 1000 
thread 2 reads counter : 1000 
thread 1 increments and writes counter: 1001 
thread 2 decrements and writes counter: 999 

С ++ и - не являются атомарными операциями, выше нить переплетения примера теряет приращение.

Самый простой способ исправить их - использовать AtomicInteger, а не int. Чтобы понять суть проблемы, лучше прочитать Java Concurrency in Practice или, по крайней мере, учебник по параллелизму Java.