zoukankan      html  css  js  c++  java
  • 简单测试Java线程安全中阻塞同步与非阻塞同步性能

    摘抄自周志明老师的《深入理解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线程用户态内核态切换损耗的处理器时间很大。

  • 相关阅读:
    ASP.NET实现进度条效果【转】
    删除指定创建日期前的文件夹、文件
    MS SQL SERVER执行大脚本文件时,提示“内存不足”的解决办法
    solr之functionQuery(函数查询)【转】
    解决Jenkins连接git时报错Permission denied (publickey)
    vscode csharp c#开发 自动引入命名空间
    nginx配置后外网无法访问
    jenkins node 版本无法使用最新的版本
    jenkins npm install WARN checkPermissions Missing write access 权限问题
    小程序setData只修改对象中的某个属性的方法
  • 原文地址:https://www.cnblogs.com/kingofkai/p/9831067.html
Copyright © 2011-2022 走看看