java基礎總結(六十一)--synchronized和cas性能對比

來自:https://www.cnblogs.com/willowWind/p/8551926.html

 

今天使用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了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章