2013-04-11 70 views
2

通過以下問題 Can synchronized blocks be faster than Atomics?
我寫了一個簡單的程序來比較的AtomicInteger的性能差異和synchronized塊去後(裏面遞增INT)。我每次運行這個程序,它給了我比> 100 我的電腦有英特爾Corei3和下面的行打印4在Java中的AtomicInteger Vs的同步int變量:性能差異

System.out.println(Runtime.getRuntime().availableProcessors()) 

當我使用

THREAD_COUNT = 1; 

的比例來最低。它改變周圍100。

THREAD_COUNT = 10; 

的比例大約是800

問題1:你能告訴我這是測試的的性能差異的正確方法的AtomicInteger VS同步的增量( ) 方法?

問題2:如果我增加THREAD_COUNT,比例增加,爲什麼?我認爲這是因爲更多線程在synchronized語句中被阻塞,並且需要更多的CPU任務。請給出意見。

package concurrent.atomic; 

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.atomic.AtomicInteger; 

public class Performance { 

    private static final AtomicInteger atomicInt = new AtomicInteger(0); 
    private static volatile int counter = 0; 
    private static final Object LOCK = new Object(); 
    private static final int THREAD_COUNT = 10; 

    public static void main(String[] args) { 

     System.out.println(Runtime.getRuntime().availableProcessors()); 

     Runnable atomic = new Runnable() { 
      @Override 
      public void run() { 
       while (!Thread.currentThread().isInterrupted()) { 
        int value = atomicInt.incrementAndGet(); 
        //if (value % 1000 == 0) 
         //System.out.println("atomic value : "+value); 
       } 
      } 
     }; 
     //System.out.println("1"); 
     Runnable intCounter = new Runnable() { 
      @Override 
      public void run() { 
       while (!Thread.currentThread().isInterrupted()) { 
        synchronized (LOCK) { 
         int value = ++counter; 
         //if (value % 1000 == 0) 
          //System.out.println("sync value "+value); 
        } 
       } 
      } 
     }; 

     final ExecutorService atomicExecutor = Executors.newCachedThreadPool(); 
     final ExecutorService primitiveExecutor = Executors.newCachedThreadPool(); 
     for (int i = 0; i < THREAD_COUNT ; ++i) { 
      atomicExecutor.submit(atomic); 
      primitiveExecutor.submit(intCounter); 
     } 

     while (true) { 
      float ratio = (((float) (atomicInt.get() * 1.0))/counter) * 100; 
      System.out.println("ratio : " + ratio); 
     } 
    } 
} 
+0

http://kennethxu.blogspot.in/2009/05/atomicinteger-vs-synchronized-monitor.html執行此操作。發現這個谷歌搜索。嘗試這個。 – 2013-04-11 12:55:44

+1

這裏有個bug,你需要將'counter'聲明爲volatile。否則,不能保證主線程讀取最新值。 – 2013-04-11 14:16:45

+0

是的..我需要改變我的代碼。 – HakunaMatata 2013-04-11 14:23:32

回答

0

問題1:你能告訴我這是測試同步的增量()方法的AtomicInteger VS的性能差異的正確方法是什麼?

有一些細微的問題,你的測試代碼:

  • 如果您在LOCK同步然後counter不應該volatile。否則​​代碼支付鎖 a volatile
  • 如果counter不是volatile那麼當讀取counter的值時,您將需要在LOCK上同步。
  • 你不應該在你的主線程中旋轉。這將會大幅影響你的性能測試。至少在您的while循環中放入Thread.sleep(100);
  • 原來,Thread.currentThread().isInterrupted()在我的Mac上很貴。不知道爲什麼。切換到while(true)改變了數字。

有了這個,你可以更好地測試兩者,雖然這樣的獨立測試並沒有告訴我們除了你正在測試的東西以外的其他任何東西。連續做一百萬箇中斷非常不同,然後將20箇中斷混合成實際代碼。

問題2:如果我增加THREAD_COUNT,比例會增加,爲什麼?我認爲這是因爲更多線程在synchronized語句中被阻塞,並且需要更多的CPU任務。請給出意見。

AtomicInteger.incrementAndGet()通過旋轉工作直到測試成功。這與完成鎖定獲取,增量和釋放完全不同。在不知道精確的操作系統線程處理細節的情況下,很難解釋這裏發生的事情,我不確定這在任何情況下都是如此。

在我的測試中,線程數越來越多,超過了我的處理器數量,這個比例趨於波動很大。隨着更多的線程被添加,synchronize處理明顯受到併發性增加的影響,儘管我不確定我還能從中得出什麼。