Synchronized 、Atomic 对比 -- JAVA 进阶

来源:互联网 发布:mac电脑卸载 编辑:程序博客网 时间:2024/06/11 12:37

在学习CAS无锁时候,总是难免拿来与Synchronized进行比较。
首先先来说一下无锁算法的基本思想:
要实现无锁(lock-free)的非阻塞算法有多种实现方法,其中 CAS(比较与交换,Compare and swap) 是一种有名的无锁算法。CAS, CPU指令,在大多数处理器架构,包括IA32、Space中采用的都是CAS指令,CAS的语义是“我认为V的值应该为A,如果是,那么将V的值更新为B,否则不修改并告诉V的值实际为多少”,CAS是项 乐观锁 技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。
这里讲一个JVM当中的CAS应用:

JVM对CAS的支持:AtomicInt, AtomicLong.incrementAndGet()    具体事例(下面会用到):     /**      * Atomically increments by one the current value.      *      * @return the updated value      */     public final long incrementAndGet() {         for (;;) {             long current = get();             long next = current + 1;             if (compareAndSet(current, next))                 return next;         }     }

为了比较其与Synchronized关键字的性能比较,我在这里做了一个测试,测试结果:
这里写图片描述

通过以上对比可以明显的发现,使用Atomic的性能要优于Synchronized
具体的代码实现:首先,设计一个类,用于记录运行的时间:

package com.test;public class StopWatch {    private long starttime =0;    private long stoptime =0;    private boolean running =false;    public void start() {        // TODO Auto-generated method stub        this.starttime = System.currentTimeMillis();        this.running = true;    }    public void stop() {        // TODO Auto-generated method stub        this.stoptime = System.currentTimeMillis();        this.running = false;    }    public long getRunningTime() {        // TODO Auto-generated method stub        long runningTime;        if(running){            runningTime = System.currentTimeMillis()-starttime;        }else{            runningTime = stoptime-starttime;        }        return runningTime;    }    public long getRunningTimeSec() {        // TODO Auto-generated method stub        long runningTimeSec;        if(running){            runningTimeSec = (System.currentTimeMillis()-starttime)/1000;        }else{            runningTimeSec = (stoptime-starttime)/1000;        }        return runningTimeSec;    }}

接着是测试类的内容:

package com.test;import java.util.concurrent.atomic.AtomicLong;public class SyncAtomicTest {    public static void main(String[] args) {        System.out.println("------START !------");        calc();  //不加任何绑定        calcSyn();   //单线程Synchronized关键字        calcAtomic();   //单线程Atomic关键字        testThreadsSync();   //多线程Synchronized关键字        testThreadAtomic();  //多线程Synchronized关键字        testThreadsSync();          testThreadAtomic();        System.out.println("------FINISHED !------");    }    private static void calc() {        // TODO Auto-generated method stub        StopWatch sw = new StopWatch();        sw.start();        long var =0;        while(var<10000000L){            var++;          }        long runningTime = sw.getRunningTime();        System.out.println("calc runningTime: "+runningTime);    }    private static void calcSyn() {        // TODO Auto-generated method stub        StopWatch sw = new StopWatch();        sw.start();        long var =0;        while(var<10000000L){            synchronized (SyncAtomicTest.class) {                var++;              }        }        long runningTime = sw.getRunningTime();        System.out.println("calcSyn runningTime: "+runningTime);    }    private static void calcAtomic() {        // TODO Auto-generated method stub        StopWatch sw = new StopWatch();        sw.start();        AtomicLong var =new AtomicLong(0);        while(var.incrementAndGet()<10000000L){        }        long runningTime = sw.getRunningTime();        System.out.println("calcAtomic runningTime: "+runningTime);    }    private static void testThreadsSync() {        // TODO Auto-generated method stub        StopWatch sw = new StopWatch();        sw.start();        Thread t1 = new Thread(new LoopSync());        t1.start();        Thread t2 = new Thread(new LoopSync());        t2.start();        while(t1.isAlive()||t2.isAlive()){        }        sw.stop();        long runningTime = sw.getRunningTime();        System.out.println("thread sync runningTime :"+ runningTime);    }    private static class LoopSync implements Runnable{        @Override        public void run() {            // TODO Auto-generated method stub            long var =0;            while(var <10000000L){                synchronized (SyncAtomicTest.class) {                    var++;                }            }        }    }    private static void testThreadAtomic() {        // TODO Auto-generated method stub        StopWatch sw = new StopWatch();        sw.start();        Thread t1 = new Thread(new LoopAtomic());        t1.start();        Thread t2 = new Thread(new LoopAtomic());        t2.start();        while(t1.isAlive()||t2.isAlive()){}        sw.stop();        long runningTime = sw.getRunningTime();        System.out.println("thread atomic runningTime :"+ runningTime);    }    private static class LoopAtomic implements Runnable{        @Override        public void run() {            // TODO Auto-generated method stub            AtomicLong var =new AtomicLong(0);            while(var.incrementAndGet() <10000000L){            }        }    }}
原创粉丝点击