简单测试Java线程安全中阻塞同步与非阻塞同步性…

2018-10-23 03:05:37来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

摘抄自周志明老师的《深入理解Java虚拟机:JVM高级特性与最佳实践》13.2.2 线程安全的实现方法

1.名词解释

同步是指锁哥线程并发访问共享数据时,保证共享数据同一时刻只被一个线程访问

互斥同步(阻塞同步)是一种悲观的并发策略,总是认为只要不去做正确的同步措施(加锁),那就肯定会出现问题。

阻塞同步最主要的问题是进行线程阻塞和唤醒所带来的性能问题,因为在JDK 1.2之后,Java的线程模型被替换为基于操作系统原生线程模型来实现,如要阻塞唤醒一个线程,都需要操作系统来帮忙完成,这就需要用户态转换到内核态,会耗费很多时间。

非阻塞同步:随着硬件指令集的发展,我们有了另一种选择:基于冲突检测的乐观并发策略,这种操作不需要挂起线程,会节省很多时间,比如CAS(compare and swap)指令。

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方式:

    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个自增,输出时间差,可以看到性能之间的差异。

lock方法平均在1270ms

cas方法平均在175ms

可以看到阻塞同步与非阻塞同步之间巨大的差异,也可以看出Java线程用户态内核态切换损耗的处理器时间很大。

 

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:Java高级面试题及答案

下一篇:Redisson分布式锁实现