java使用synchronized和cas性能对比

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

 

posted on 2018-03-12 20:57  willowWind  阅读(3482)  评论(3编辑  收藏  举报