摘抄自周志明老師的《深刻理解Java虛擬機:JVM高級特性與最佳實踐》13.2.2 線程安全的實現方法安全
1.名詞解釋併發
同步是指鎖哥線程併發訪問共享數據時,保證共享數據同一時刻只被一個線程訪問ide
互斥同步(阻塞同步)是一種悲觀的併發策略,老是認爲只要不去作正確的同步措施(加鎖),那就確定會出現問題。性能
阻塞同步最主要的問題是進行線程阻塞和喚醒所帶來的性能問題,由於在JDK 1.2以後,Java的線程模型被替換爲基於操做系統原生線程模型來實現,如要阻塞喚醒一個線程,都須要操做系統來幫忙完成,這就須要用戶態轉換到內核態,會耗費不少時間。測試
非阻塞同步:隨着硬件指令集的發展,咱們有了另外一種選擇:基於衝突檢測的樂觀併發策略,這種操做不須要掛起線程,會節省不少時間,好比CAS(compare and swap)指令。spa
2.開始測試操作系統
第一種加鎖方式:線程
static int a=0; public static void lock() { Thread[] threads=new Thread[50]; for(int i=0;i<threads.length;i++){ threads[i]=new Thread(new Runnable() { @Override public void run() { for(int i=0;i<100000;i++){ synchronized(Main.class){ a++; } } } }); threads[i].start(); } while(Thread.activeCount() > 1){ Thread.yield(); } System.out.println(a); }
第二種CAS方式:code
static AtomicInteger integer=new AtomicInteger(0); public static void cas() { Thread[] threads=new Thread[50]; for(int i=0;i<threads.length;i++){ threads[i]=new Thread(new Runnable() { @Override public void run() { for(int i=0;i<100000;i++){ integer.incrementAndGet(); } } }); threads[i].start(); } while(Thread.activeCount() > 1){ Thread.yield(); } System.out.println(integer.get()); }
3結論:運行兩個方法,一樣是50個線程,100000個自增,輸出時間差,能夠看到性能之間的差別。blog
lock方法平均在1270ms
cas方法平均在175ms
能夠看到阻塞同步與非阻塞同步之間巨大的差別,也能夠看出Java線程用戶態內核態切換損耗的處理器時間很大。