2016-05-02 83 views
0

因爲這是我在stackoverflow上的第一個問題,所以我會盡力解釋它。Java線程同時遞增和遞減一個int

如果這是一個重複的問題,我很抱歉,但我花了很多時間搜索並找不到答案。 由於我不久前開始學習線程,現在遇到了一個障礙:D 我想編寫一個NOT線程安全的方法,使用兩個線程同時遞增和遞減整數。

所以到目前爲止,我的代碼是這樣的..可悲的是不工作,我不知道爲什麼

public class ThreadFunctions { 
    private int counter = 0; 
    private boolean command = false; 

    public synchronized void changeNumber(boolean command){ 
     this.command = command; 
     synchronized (this) { 
      if(command){ 
       counter++; 
      }else{ 
       counter--; 
      } 
     } 
    } 

    public synchronized int getCounter(){ 
     return this.counter; 
    } 
} 

就這樣,我用它來測試它的類。

public class Demo{ 
    public static void main(String[] args){ 

    final ThreadFunctions o = new ThreadFunctions(); 

    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      while(o.getCounter() < 100){ 
       o.changeNumber(true); 
       System.out.println("Thread: " + Thread.currentThread().getId() + " counter: "+o.getCounter()); 
      } 
     } 
    }).start(); 

    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      while(o.getCounter() > -100){ 
       o.changeNumber(false); 
       System.out.println("Thread: " + Thread.currentThread().getId() + " counter: "+ o.getCounter()); 
      } 
     } 
    }).start(); 
    } 
} 

,結果是這樣的......

Thread: 10 counter: 5 
Thread: 10 counter: 6 
Thread: 10 counter: 7 
Thread: 10 counter: 8 
Thread: 10 counter: 9 
Thread: 11 counter: 8 
Thread: 10 counter: 9 
Thread: 10 counter: 10 
Thread: 10 counter: 11 
Thread: 10 counter: 11 
Thread: 10 counter: 12 
Thread: 10 counter: 13 
Thread: 11 counter: 13 

etc.. 

所以就像你看到的線程仍然不同步,我不明白爲什麼:(

+0

多線程代碼很難讓優秀的程序員編寫。您不應該使用像synchronized和Thread這樣的純粹的JDK 1.0結構。我建議從java.util.collections和java.util.concurrent更新的類。 – duffymo

+0

您的預期成果是什麼? – Vampire

+0

順便說一句,當你在方法定義級別使用synchronized關鍵字時,同步(this)是無用的 –

回答

0

要使它是非線程安全的,刪除​​關鍵字

public void changeNumber(boolean command){ 
      if(command){ 
       counter++; 
      }else{ 
       counter--; 
     } 
    } 
1

爲了確保in的原子性加/減量操作,您可以改爲AtomicInteger

你的情況,以確保原子性,而不是incrementing/decrementing然後getting未自動完成的,因爲它們不是同一個synchronized塊內完成,你應該只使用一個方法,做到既像這樣的價值:

public synchronized int changeNumber(boolean command){ 
    this.command = command; 
    if (command){ 
     counter++; 
    } else { 
     counter--; 
    } 
    return counter; 
} 

然後由線程執行的代碼將是:

while(o.getCounter() < 100) { 
    System.out.println(
     "Thread: " + Thread.currentThread().getId() + " counter: " + o.changeNumber(true) 
    ); 
} 

while(o.getCounter() > -100) { 
    System.out.println(
     "Thread: " + Thread.currentThread().getId() + " counter: " + o.changeNumber(false) 
    ); 
} 
0

每個線程重複遞增/遞減和打印。 但是另一個線程可以像這樣在遞增/遞減和打印之間運行。

OUTPUT     THREAD 10 THREAD 11 COUNTER 
---------------------- --------- --------- ------- 
Thread: 10 counter: 9 print      9 
         increment     10 
Thread: 10 counter: 10 print      10 
         increment     11 
Thread: 10 counter: 11 print      11 
            decrement  10 
         increment     11 
Thread: 10 counter: 11 print      11 
         increment     12 
Thread: 10 counter: 12 print      12 
         increment     13 
Thread: 10 counter: 13 print      13 
Thread: 11 counter: 13    print   13 

如果你想避免這種情況,你應該同步增加/減少和打印像這樣。

public synchronized void changeNumber(boolean command) { 
     this.command = command; 
     synchronized (this) { 
      if (command) { 
       counter++; 
      } else { 
       counter--; 
      } 
      System.out.println("Thread: " + Thread.currentThread().getId() + " counter: " + counter); 
     } 
    }