2017-09-04 16 views
0

我在採訪中被告知,在運行下面的代碼之後計數器的最小值是2.這怎麼可能?兩個線程在沒有同步的情況下訪問的計數器的最小值

class ThreadsConflict { 
      private static int counter = 0; 

      public static void main(String[] args) throws InterruptedException{ 
        Thread t1 = new A(); 
        Thread t2 = new A(); 
        t1.start(); 
        t2.start(); 

        t1.join(); 
        t2.join(); 

        System.out.println(counter); 
      } 

      static class A extends Thread { 
        public void run() { 
          for(int i = 0; i < 10; i++) { 
            counter++; 
          } 
        } 
      } 
    } 

我可以理解爲什麼這將是10,如果他們交織並++運算符是相互矛盾的,但是這怎麼可能,這將是在10?

回答

1

這是因爲交錯非原子操作,以便counter++可以在中間被打斷之間出現,有點:

int tmp = counter; 
/* threads gets interrupted here */ 
counter = tmp + 1; 

這可能會導致極端情況情形爲:

  • 線程A讀取0
  • 線程B讀取0並寫入1
  • 線程B讀取1並寫入2
  • ...
  • 線程B 8讀取和寫入9
  • 線程A將1寫入
  • 線程B讀取1
  • 線程A 1讀取和寫入2
  • 線程A 2讀取和寫入3
  • ...
  • 線程A讀取9和寫入10
  • 線程A完成
  • 線程B寫入2
  • 線程B完成

記住,這是因爲i作爲條件,使整整10次迭代完成後,如果您使用直接counter,那麼你就可以保證至少有10

+0

我明白你是如何達到'2'的,但爲什麼它很小? (只是有興趣) – OldCurmudgeon

+1

因爲沒有更糟糕的方式(從線程的角度來看)線程將運行。 – Tomer

+0

我已經運行了這麼多次,結果從10到20.它將取決於系統中的線程數,哪個線程獲取CPU和何時。在B出發之前,A可以完全結束。雖然你的情況是可能的,但這是不太可能的。 – edharned

相關問題