今天使用synchronized和java unsafe cas接口對比了下同一個操作下的的相關性能,
為后面多線程情況下使用synchronized同步阻塞方式或者是unsafe cas非阻塞做了一個參考。
測試用例:
啟用多個線程進行計數相加到一億,首先是synchronized方式;
計算類如下:
package com.wc.thread; public class SyncCounter implements CountBase{ private volatile long value = 0; @Override public synchronized long getValue() { // TODO Auto-generated method stub return value; } @Override public synchronized long increment() { // TODO Auto-generated method stub if (value <= 100000000) return ++value; else return value; } }
測試類:
package com.wc.thread; public class Test { public static void main(String[] args) { CountBase counter= new SyncCounter(); for(int i =0; i< 64; i++) { Thread thread = new Thread(new Runnable() { @Override public void run() { long begin = System.currentTimeMillis(); while(true) { if(counter.getValue() >= 100000000) break; else { counter.increment(); } } long end = System.currentTimeMillis(); long time = end - begin; System.out.println("The process is " + Thread.currentThread().getName() + " Value is :" + counter.getValue() + ";" + "time is:" + time); } } ); thread.start(); } } }
測試相關數據如下:
當線程數為8時,性能明顯提升,但是8到32個線程來說,每個線程的平均時間基本差不多,基本沒有提升,到了64個線程的時候,性能又有一點提升。
如果換成CAS實現多線程累加數為一億,時間又會怎么樣呢,我們先來看下測試代碼:
計算類如下:
package com.wc.thread; import java.lang.reflect.Field; import sun.misc.Unsafe; public class CasCounter implements CountBase{ private volatile long value = 0; private static Unsafe un; private static long valueOffset; static { try{ un = getUnsafeInstance(); valueOffset = un.objectFieldOffset(CasCounter.class.getDeclaredField("value")); }catch (Exception e) { // TODO: handle exception System.out.println("init unsafe error!"); } } @Override public long getValue() { // TODO Auto-generated method stub return value; } @Override public long increment() { // TODO Auto-generated method stub long current; long next; for(;;) { current = value; next = current + 1; if(value >= 100000000) return value; if(un.compareAndSwapLong(this, valueOffset, current, next)) return next; } } private static Unsafe getUnsafeInstance() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafeInstance.setAccessible(true); return (Unsafe) theUnsafeInstance.get(Unsafe.class); } }
測試類和之前類似,只需要用CasCounter類實例化CountBase接口即可;
統計數據如下:
對比兩個結果我們可知:
在線程數相對較少的時候,CAS實現比較快,性能優於synchronized,當線程數多於8后,CAS實現明顯開始下降,反而時間消耗高於synchronized;
以上結果表明,synchronized是java提供的又簡單方便,性能優化又非常好的功能,建議大家常用;CAS的話,線程數大於一定數量的話,多個線程在
循環調用CAS接口,雖然不會讓其他線程阻塞,但是這個時候競爭激烈,會導致CPU到達100%,同時比較耗時間,所以性能就不如synchronized了。