多线程优化(性能调优)

7 篇文章 0 订阅
订阅专栏

目录

1.多线程基础

性能相关基础:

上下文切换:

2.多线程锁优化

2.1 案例

2.2 优化方案1--使用原子操作类AtomicXXX

2.2 LongAdder对象

3.多线程之并发容器优化

4.多线程之线程池优化


1.多线程基础

性能相关基础:

上下文切换:

无论是单核cpu还是多核cpu,都会有cpu时间片(分配给线程的运行时间),现在有两种情况:

  • 线程1 运行完了
  • 线程1 阻塞,挂起

当上述两种情况发生,就会发生上下文切换。上文:保存进度。下文:加载进度

上文:线程1 进度(执行进度信息,如执行完,执行了60%以后阻塞挂起)。

下文:线程2 进度(下一个线程执行信息,可能之前执行过,然后被唤醒)。

主频为1GHz的cpu执行一条cpu指令,耗时是1ns。一次上下文切换大约耗时8微秒=8000纳秒。

2.多线程锁优化

2.1 案例

先看这样一段代码:

public class LockTest {
    long count = 0;

    public void access(){
        count++;
    }
    public static void main(String[] args) throws InterruptedException {
        LockTest lockTest = new LockTest();
        for (int i=0;i<10;i++){
            new Thread(()->{
                for (int j=0;j<1000;j++){
                    lockTest.access();
                }
            }).start();
        }
        Thread.sleep(5000);
        System.out.println(lockTest.count);
    }
}

 该代码设置了10个线程,每个线程内对count执行1000次加一操作。由于线程安全问题,代码中打印的count的值一定是小于等于10000的。所以要对其进行优化。

2.2 优化方案1--使用原子操作类AtomicXXX

优化代码如下所示:

public class LockTest {
    //    long count = 0;
    AtomicLong count = new AtomicLong();
    public void access(){
        count.incrementAndGet();
    }
    public static void main(String[] args) throws InterruptedException {
        LockTest lockTest = new LockTest();
        for (int i=0;i<10;i++){
            new Thread(()->{
                for (int j=0;j<1000;j++){
                    lockTest.access();
                }
            }).start();
        }
        Thread.sleep(5000);
        System.out.println(lockTest.count);
    }
}

 AtomicLong类中的部分代码如下所示。

    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;    

    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicLong.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

    private volatile long value;


    public final long incrementAndGet() {
        return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
    }

 这个value也就是上述代码中的count的值,在静态代码块中根据value获取count的内存偏移地址,然后将AtomicLong对象和value属性偏移地址传入unsafe.getAndAddLong()方法中,该方法代码如下所示:

public final long getAndAddLong(Object var1, long var2, long var4) {
        long var6;
        do {
            var6 = this.getLongVolatile(var1, var2);
        } while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));

        return var6;
    }

 根据传入的AtomicLong对象和value偏移地址获取到value的值,赋值给var6,然后进行cas操作,具体百度cas原理。这里不再详细赘述。

基于cas实现的原子操作类,优势在哪?对比锁sync Lock。

没有上下文切换。假设一行java代码,cpu循环一次需要10ns,10个线程,按照平均法则分配cpu资源,10ns*10=100ns,

加锁10个线程,需要9次上下文切换,9*8微秒=72微秒=72000ns

总结:cas原子操作类  lock锁 sync锁

2.2 LongAdder对象

atomic还可以进一步优化么?如果是jdk8,推荐使用LongAdder对象,比AtomicLong性能更好(减少乐观锁的重试次数)

代码实现:

public class LockTest {
    //    long count = 0;
//    AtomicLong count = new AtomicLong(); //原子操作类
    LongAdder count = new LongAdder();
    public void access(){
        count.add(1);
    }
    public static void main(String[] args) throws InterruptedException {
        LockTest lockTest = new LockTest();
        for (int i=0;i<10;i++){
            new Thread(()->{
                for (int j=0;j<1000;j++){
                    lockTest.access();
                }
            }).start();
        }
        Thread.sleep(5000);
        System.out.println(lockTest.count);
    }
}

atomicXXX和LongAdder的区别:分裂value,类似于分布式cas,分裂共享资源,最后累加。减少了乐观锁的自旋次数。

 性能对比:

public class LongAdderTest {
    public static void main(String[] args) {
        testAtomicLongVSLongAdder(10,10000);
        testAtomicLongVSLongAdder(20,200000);
        testAtomicLongVSLongAdder(30,200000);
    }

    //多线程并发模拟及耗时统计
    private static void testAtomicLongVSLongAdder(final int threadcount, final int time) {
        try {
            long start = System.currentTimeMillis();
            testAtomicLong(threadcount,time);
            long end = System.currentTimeMillis()-start;
            System.out.println("Atomic-time:"+end);

            long start1 = System.currentTimeMillis();
            testLongAdder(threadcount,time);
            long end1 = System.currentTimeMillis()-start1;
            System.out.println("LongAdder-time:"+end1);
        }catch (InterruptedException e){
            e.printStackTrace();
        }



    }

    private static void testLongAdder(final int threadcount,final int time) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(threadcount);
        LongAdder longAdder = new LongAdder();
        for (int i=0;i<threadcount;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j=0;j<time;j++){
                        longAdder.add(1);
                    }
                    countDownLatch.countDown();
                }
            },"mythread"+i).start();
        }
        countDownLatch.await();
    }

    private static void testAtomicLong(final int threadcount,final int time) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(threadcount);
        AtomicLong atomicLong = new AtomicLong();
        for (int i=0;i<threadcount;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j=0;j<time;j++){
                        atomicLong.incrementAndGet();
                    }
                    countDownLatch.countDown();
                }
            },"mythread"+i).start();
        }
        countDownLatch.await();
    }

}

运行结果:

10个线程数量,10000次数Atomic-time:4
10个线程数量,10000次数LongAdder-time:5
20个线程数量,200000次数Atomic-time:67
20个线程数量,200000次数LongAdder-time:28
30个线程数量,200000次数Atomic-time:76
30个线程数量,200000次数LongAdder-time:5

当线程数较少时(10个线程),LongAdder的分裂操作和最后加和操作耗费的时间相对于cas操作的时间来说就比较明显。优化效果不明显,因为LongAdder的分裂操作和加操作也会耗费一定的时间。

当线程数较多时,优化效果就很明显。

atomicXXX:强一致性

LongAdder:弱一致性

1、强一致性:在任何时刻所有的用户或者进程查询到的都是最近一次成功更新的数据。强一致性是程度最高一致性要求,也是最难实现的。关系型数据库更新操作就是这个案例。简而言之:就是操作完以后立刻拿到数据进行一致性核实。大厂高并发很少有强一致性!!!!!atomic在执行完cas操作以后就会立刻获取数据核实,因此是强一致性。

2、最终一致性:和强一致性相对,在某一时刻用户或者进程查询到的数据可能都不同,但是最终成功更新的数据都会被所有用户或者进程查询到。当前主流的nosql数据库都是采用这种一致性策略。LongAdder在执行完cas操作以后还要对各个结果进行求和以后才会核验一致性,因此是弱一致性。

锁优化过程: 

 

 

3.多线程之并发容器优化

HashMap--->ConcurrentHashMap

ArrayList--->CopyOnWriteArrayList:适合于多读多写的场景。

实现原理:写时复制,当写入数据的时候,CopyOnWriteArrayList会先进行扩容操作,将老的数据复制到新的数组中。如果此刻有个读的线程来操作资源,当写线程还没完成时,则数组指针还是指向未扩容的老数组,故读的数据还是老数据。若此时写线程已经完成工作,则数组指针就会指向新的数组,此时读到的数据是新的数据。

4.多线程之线程池优化

 这些指标都存在与两个map中:

//线程池整个运行状态,存放多个runnableNameMap,key--task,value--runnableNameMap
public Map<String,Map> transactionMap = new ConcurrentHashMap<>();
//存储单个任务状态
public Map<String,String> runnableNameMap= new ConcurrentHashMap<>();

探索并发编程(六)------Java多线程性能优化
走向架构师之路
08-05 3万+
大家使用多线程无非是为了提高性能,但如果多线程使用不当,不但性能提升不明显,而且会使得资源消耗更大。下面列举一下可能会造成多线程性能问题的点:死锁过多串行化过多锁竞争切换上下文内存同步下面分别解析以上性能隐患死锁关于死锁,我们在学习操作系统的时候就知道它产生的原因和危害,这里就不从原理上去累述了,可以从下面的代码和图示重温一下死锁产生的原因:public class LeftRightDeadlock { private final Object left = new Object();
c语言多线程性能调优,C++性能优化(八)——内存分配机制
weixin_29854481的博客
05-24 1409
C++性能优化(八)——内存分配机制一、操作系统内存布局1、32位系统经典内存布局Linux Kernel 2.6.7前版本采用的默认内存布局形式如下:(1)32操作系统中,loader将可执行文件的各个段次依次载入到从0x80048000(128M)位置开始的空间中。应用程序能够访问的最后地址是0xbfffffff(3G)的位置,3G以上的位置是给内核使用的,应用程序不能直接访问。(2)内存布局...
多线程性能及效率问题
cczakai的专栏
10-13 1061
一、[多线程概要]  随着计算机技术的发展,编程模型也越来越复杂多样化。但多线程编程模型是目前计算机系统架构的最终模型。随着CPU主频的不断攀升,X86架构的硬件已经成为瓶,在这种架构的CPU主频最高为4G。事实上目前3.6G主频的CPU已经接近了顶峰。  如果不能从根本上更新当前CPU的架构(在很长一段时间内还不太可能),那么继续提高CPU性能的方法就是超线程CPU模式。那么,作业系统、应用程序...
线程池怎么调优?线程池的几种方式?及线程池的实战
最新发布
weixin_60153382的博客
07-24 1803
线程池的调优
Android性能优化典范(五)
唐小引的 CSDN 博客
04-29 1786
作者简介: 胡凯(@胡凯me),腾讯Android工程师,热爱开源与分享,维护Android官方培训课程协作项目,关注Android应用性能优化的总结与分享,推崇Android官方最佳实践。个人博客:http://hukai.me,Github:https://github.com/kesenhoo。 序言这是Android性能优化典范第5季的课程学习笔记,拖拖拉拉很久,记录分享给...
多线程性能调优
weixin_40805537的博客
06-15 5128
原文:https://time.geekbang.org/column/article/101244#previewimg Lock 同步锁是基于 Java 实现的。 Synchronized 是基于底层操作系统的Mutex Lock 实现的,每次获取和释放锁操作都会带来用户态和内核态的切换,从而增加系统性能开销。 Synchronized 在修饰同步代码块时,是由 monitorenter 和m...
多线程调优
烈冬冰夏的博客
09-25 297
上下文切换是什么 分时系统中,一个线程被暂停剥夺使用权,另外一个线程被选中开始或者继续运行的过程就是上下文切换。 一个线程的状态由 RUNNING 转为 BLOCKED ,再由 BLOCKED 转为 RUNNABLE ,然后再被调度器.选中执行,这就是一个上下文切换的过程。 线程生命周期 线程主要有“新建”(NEW)、“就绪”(RUNNABLE)、“运行”(RUNNING)、“阻塞”(BLOC...
阿里巴巴Java性能调优实战(2021-2022华山版)+Java架构核心宝典+性能优化手册100技巧.rar
11-08
模块三,多线程性能调优。 模块四,JVM 性能监测及调优。 模块五,设计模式调优。 模块六,数据库性能调优。 模块七,实战演练场。 性能优化手册是一套java性能学习研究小技巧,包含内容:Java性能优化、JVM性能优化...
linux性能调优.pdf
07-22
Linux性能调优是系统管理员和开发人员...总而言之,Linux性能调优是一个系统化的过程,需要从性能分析、工具使用、指标监控等多个维度进行。通过合理的规划和调整,我们能够使Linux系统更好地满足应用和用户的需求。
MySQL性能调优与架构设计.pdf
01-19
1. MySQL 简介:MySQL 是由 MySQL AB 公司研发的开源数据库管理系统,支持多线程高并发多用户,具有简单高效可靠的特点。 2. MySQL 发展历程: MySQL 的诞生可以追溯到 1985 年,瑞典的几位志同道合小伙子成立了...
阿里巴巴Java性能调优实战(2021华山版)
01-22
模块三主要讲解多线程性能调优,包括多线程编程的应用、线程安全性、多线程高并发带来的性能问题等。 模块四:JVM 性能监测及调优 模块四主要讲解 JVM 性能监测及调优,包括 Java 对象的创建和回收、内存分配等。 ...
Java | 多线程调优(上):哪些操作导致了上下文切换?
sinat_27143551的博客
10-25 2826
我们常说“实践是检验真理的唯一标准”,这句话不光在社会发展中可行,在技术学习中也同样适用。记得我刚入职上家公司的时候,恰好赶上了一次抢购活动。这是系统重构上线后经历的第一...
java多线程程序性能调优 优化过程
jonfoo_W的专栏
11-30 5588
我, 一多年c++开发,由于项目原因需要对一个性能底下的多线程java程序进行调优,百度google了几把,妈蛋,没有发现指导如何java线程调优的文章啊,都是一些java使用规范,我去,那我大java的开发工程师都是怎么调优的啊, 那我大C++工程师就带领大家如何java调优了,下面就转入正题了! 有句话叫“只要推力大,板砖也能飞上天”, 那换到我们it, 只要cpu强大,那么再烂的程序也能跑
如何设置线程池参数大小?
田维常
05-18 3427
关注Java后端技术栈“回复“面试”获取最新资料我们在使用线程池的时候,会有两个疑问点:线程池的线程数量设置过多会导致线程竞争激烈如果线程数量设置过少的话,还会导致系统无法充分利用计算机...
Java多线程性能调优
m0_46202211的博客
07-12 1159
1.6之前比较重量级,1.6后经过优化性能大大提升使用Synchronized实现同步锁住要是两种方式:方法、代码块。1.代码块Synchronized在修饰同步代码块时,是由 monitorenter和monitorexit指令来实现同步的。进入monitorenter 指令后,线程将持有Monitor对象,退出monitorenter指令后,线程将释放该Monitor对象。2.方法。
第十二章Java多线程程序的性能调优
qq_41916811的博客
01-16 387
Java虚拟机对内部锁的优化 锁消除 锁消除优化能否被实施还取决于被调用的同步方法(或者带同步块的方法)是否能够被内联。 在锁消除的作用下,利用ThreadLocal将一个线程安全的对象(比如Random)作为一个线程特有对象来使用,不仅可以避免锁的争用,还可以彻底消除这些对象内部所使用的锁的开销。 锁粗化 锁粗化可能导致一个线程持续持有一个锁的时间变长,从而使得同步在该锁之上的其他线程在申请...
多核多线程优化
qq_39690821的博客
01-02 1585
源址:https://www.ibm.com/developerworks/cn/linux/l-cn-optimization/index.html 样例程序 程序功能:求从1一直到 APPLE_MAX_VALUE (100000000) 相加累计的和,并赋值给 apple 的 a 和 b ;求 orange 数据结构中的 a[i]+b[i ] 的和,循环 ORANGE_MAX_
多线程性能调优多线程调优(下):如何优化多线程上下文切换?
ChinaLiaoTian的博客
03-08 312
竞争锁优化:在多线程编程中,锁其实不是性能开销的根源,竞争锁才是。锁的优化归根结底就是减少竞争。 a. 减少锁的持有时间:可以将一些与锁无关的代码移出同步代码块,尤其是那些开销较大的操作以及可能被阻塞的操作; b. 降低锁的粒度:同步锁可以保证对象的原子性,我们可以考虑将锁粒度拆分得更小一些,以此避免所有线程对一个锁资源的竞争过于激烈。如锁分离、锁分段; c. 非阻塞乐观锁替代竞争锁:CAS; wait/notify 优化:使用 Lock 锁结合 Condition 接口替代 Synchronized 内.
写文章

热门文章

  • redis加锁的几种方式 4139
  • spring AOP注解失效原因 3974
  • 多线程优化(性能调优) 3514
  • kafka-consumer-消费者代码实例 2593
  • kafka-consumer-offset位移 2522

分类专栏

  • java 13篇
  • nginx 1篇
  • 工具使用 4篇
  • golang 2篇
  • docker 1篇
  • 其他
  • 网络 1篇
  • kafka 11篇
  • 设计模式 7篇
  • mysql 6篇
  • 异常处理 1篇
  • spring 7篇
  • redis 4篇
  • 面试 3篇
  • 分布式 1篇
  • mybatis 1篇
  • es 1篇
  • 多线程 7篇

最新评论

  • java发送https请求支持tls1.3

    CSDN-Ada助手: 推荐 网络 技能树:https://edu.csdn.net/skill/network?utm_source=AI_act_network

  • nginx搭建简单负载均衡demo(springboot)

    普通网友: 优质好文,博主的文章细节很到位,兼顾实用性和可操作性,感谢博主的分享,文章思路清晰【我也写了一些相关领域的文章,希望能够得到博主的指导,共同进步!】

  • mysql:create index 和 alter add index

    SeaDhdhdhdhdh: 对的,一般没有在生产环境或者大流量的情况下使用这种方式,但是设置索引操作一般为一次操作,不直接写在代码里面跟随流量去执行,所以就在这记录了这两种方式。

  • mysql:create index 和 alter add index

    madmacbeth: 但是alter table方式,会导致锁表,如果直接在运行中的生产环境中,不建议用这种方式

  • GoLang基础

    CSDN-Ada助手: 推荐 Go 技能树:https://edu.csdn.net/skill/go?utm_source=AI_act_go

最新文章

  • java发送https请求支持tls1.3
  • java读取大文件报错
  • nginx搭建简单负载均衡demo(springboot)
2024年7篇
2023年19篇
2022年41篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

天下网标王网站推广优化诊断网站优化效果评估标准山东济南网站优化学校大连靠谱的机械行业网站优化黑龙江网站优化价格表行车无锡网站优化维修保养百度seo网站优化最新报价网站文章怎么优化才有效网站搜索引擎优化有哪些推广优化网站排名技术青岛在线网站优化网站搜索排名优化晓得易速达能源网站优化公司网站如何做进一步优化从网站看哪个公司做的优化河南瓷砖行业网站优化推广怎么样江门专业网站优化多少钱琼海如何优化网站江南都市花园搜狗网站优化张家港网站优化企业利于优化的织梦网站如何优化网站完善火2星优秀施甸县网站seo优化排名免费网站seo优化软件凤城网站优化优化网站男人补肾香河网站优化价格怎么做网站优化西凤酒网站搜索引擎优化网站每个页面都要优化代码吗香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声卫健委通报少年有偿捐血浆16次猝死汪小菲曝离婚始末何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言男子被猫抓伤后确诊“猫抓病”周杰伦一审败诉网易中国拥有亿元资产的家庭达13.3万户315晚会后胖东来又人满为患了高校汽车撞人致3死16伤 司机系学生张家界的山上“长”满了韩国人?张立群任西安交通大学校长手机成瘾是影响睡眠质量重要因素网友洛杉矶偶遇贾玲“重生之我在北大当嫡校长”单亲妈妈陷入热恋 14岁儿子报警倪萍分享减重40斤方法杨倩无缘巴黎奥运考生莫言也上北大硕士复试名单了许家印被限制高消费奥巴马现身唐宁街 黑色着装引猜测专访95后高颜值猪保姆男孩8年未见母亲被告知被遗忘七年后宇文玥被薅头发捞上岸郑州一火锅店爆改成麻辣烫店西双版纳热带植物园回应蜉蝣大爆发沉迷短剧的人就像掉进了杀猪盘当地回应沈阳致3死车祸车主疑毒驾开除党籍5年后 原水城县长再被查凯特王妃现身!外出购物视频曝光初中生遭15人围殴自卫刺伤3人判无罪事业单位女子向同事水杯投不明物质男子被流浪猫绊倒 投喂者赔24万外国人感慨凌晨的中国很安全路边卖淀粉肠阿姨主动出示声明书胖东来员工每周单休无小长假王树国卸任西安交大校长 师生送别小米汽车超级工厂正式揭幕黑马情侣提车了妈妈回应孩子在校撞护栏坠楼校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变老人退休金被冒领16年 金额超20万西藏招商引资投资者子女可当地高考特朗普无法缴纳4.54亿美元罚金浙江一高校内汽车冲撞行人 多人受伤

天下网标王 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化