1. 程式人生 > >多執行緒中Join的運用(困惑的經典問題終於解決)

多執行緒中Join的運用(困惑的經典問題終於解決)

最近看了一個老哥的博文,發現Thread.join()的例子中每次執行結果都不一樣,特把例子貼出來:

/**
 *  Copyright (C), 2002-2012, www.chinarainbow.com.cn
 *  @{#} JoinThread.java Create on 2011-6-9 下午02:05:59
 *  @author 米飯超人
 *  @version 1.0
 *  @description 類說明
 *
 *  History
 *  Date: 2011-6-9
 *  @author
 *  @modification: 初始版本
 */
package org.threads;

import java.util.concurrent.atomic.*;

public class JoinThread extends Thread {
 private  static int n = 0;
 private static AtomicInteger sum=new AtomicInteger();
 public void run() {
  for (int i = 0; i < 10; i++)
   try {
    
    addN();
     sleep(3); // 為了使執行結果更隨機,延遲3毫秒
   } catch (Exception e) {
    e.printStackTrace();
   }
 }

 private  synchronized void addN() {
//  sum.incrementAndGet();
  n++;

 }

 public static void main(String[] args) throws Exception {
  Thread threads[] = new Thread[100];
  for (int i = 0; i < threads.length; i++) {
   threads[i] = new JoinThread();
  }
  for (int i = 0; i < threads.length; i++) {
   threads[i].start();
   
  }
  System.out.println(threads.length);
  
  // if (args.length > 0) {
  for (int i = 0; i < threads.length; i++) {
   // 100個執行緒都執行完後繼續
   threads[i].join();
   
   
  }
  
  // }
  System.out.println("n=" + JoinThread.n);
  System.out.println("AtomicInteger=" + sum.get());
 }

}

這個例子的結果是 "n" 有時候不是1000. 很長一段時間一直找不到原因,今天終於弄明白了。

問題在這裡:

 private  synchronized void addN()

如果這裡不用靜態,那麼每次執行結果是不一樣的,如果修改成靜態方法就可以,那這又是為什麼呢?靜態方法和變數是分配到stack裡,記憶體固定,非靜態是分配到heap裡,即靜態是全域性和唯一的,那麼加上synchronized 就能保證計數器正確!相反,非全域性唯一,及時加入synchronized ,是非單例模式,所以不是同步的。可能heap有多個地址,只是值一樣而已。所以最好用靜態方法呼叫靜態變數更穩妥些!