美文网首页互联网科技Java
详解Java并发的性能与可伸缩性

详解Java并发的性能与可伸缩性

作者: Java_苏先生 | 来源:发表于2019-08-20 13:46 被阅读6次

    欢迎Java工程师关注简书专栏
    Java架构技术进阶
    本专栏收录各种Java相关技术,面试题,以及学习感悟,心得!

    线程最主要的目的是提高系统的运行性能。

    始终要把安全性放在第一位,首先保证线程的安全性,只有在程序有性能要求时,才进行进一步的性能优化。

    一、性能与可伸缩性

    对于服务器应用程序来说,“多少”这个方面比“多块”这个方面更受重视。
    当进行决策时,有时候会通过增加某种形式的成本来降低另一种形式的开销。

    1.1 性能

    当进行性能调优时,其目的是用更小的代价完成相同的工作。

    1.1.1 性能优化

    要提高应用的性能,主要有两方面:

    • 有效利用现有的处理资源
    • 在出现新的处理资源时使系统尽可能的利用这些资源。

    1.1.2 指标

    程序的性能可以用多个指标衡量:

    • 程序运行速度
      服务时间,响应时间,等待时间
    • 程序处理能力
      生产量,吞吐量

    1.2 可伸缩性

    可伸缩性指,当增加计算资源时(CPU、内存、IO、带宽)时,程序的吞吐量或处理能力能相应的增加。

    1.2.1 可伸缩性优化

    目的是怎么将问题并行化。

    二、Amdahl定律

    在增加计算资源的情况下,程序在理论上能够实现最高的加速比,这个值取决于程序中可并行组件与串行组件所占的比例。
    在所有的并发程序中都包含一些串行部分。

    三、线程引入的开销

    并行带来的性能提升必须超过并发导致的开销。

    3.1 上下文切换

    1. 上下文切换的开销
    2. 缓存丢失的开销
      当线程频繁的发生阻塞,那么它们将无法使用完整的调度时间片。

    3.2 内存同步

    内存同步一般都会使用一些特殊的命令,即内存栅栏。内存栅栏可以刷新缓存,使缓存无效,刷新硬件的写缓存,以及停止执行管道,它将抑制编译器及硬件的优化操作。
    同步会加大内存总线上的通信量。

    3.3 阻塞

    竞争的同步需要操作系统的介入,增加开销。

    1. 自旋等待
      通过循环的尝试获取锁,直到成功
    2. 操作系统挂起
      由操作系统将线程移到等待队列。

    四、减少锁竞争

    在并发程序中,对可伸缩性的最主要的威胁就是独占方式的资源锁。

    4.1 原则

    原则:

    1. 降低锁的获取频率
    2. 降低持有锁的时间
      如果两者的乘积很小,那么大多数锁的操作都不会发生竞争,因此在该锁上的竞争不会对可伸缩性造成严重的影响。
    3. 使用带有协调机制的独占锁

    4.2 策略

    4.2.1 缩小锁的范围

    尽可能的缩短锁持有的时间。

    4.2.2 减少锁的粒度

    减少锁的请求频率,这可以通过锁分解和锁分段等技术实现,在这些技术中将采用多个相互独立的锁来保护独立的状态变量,从而改变这些变量在之前由单个锁保护的情况。

    4.2.2.1 锁分解

    如果一个锁需要保护多个相互独立的状态变量,那么可以将这个锁分解为多个锁,并且每一个锁只保护一个变量,从而提供可伸缩性,最终降低每个锁被请求的频率。

    4.2.2.2 锁分段

    可以将锁分解技术进一步扩展为对一组独立对象上的锁进行分解,这种情况被称为锁分段。
    ConcurrentHashMap

    4.2.3 避免热点域

    4.2.4 替代独占锁的其他方法

    4.2.4.1 ReadWriteLock

    针对读多写少得情况进行了进一步的优化。

    4.2.4.2 原子变量

    可以降低热点域的开销

    4.2.5 拒绝对象池

    线程分配新的对象时,基本上不需要在线程间进行协调,直接从线程本地内存块进行分配即可。
    通常,对象分配操作的开销比同步开销更低。

    4.2.6 监控CPU利用率

    • 负载不充足
    • IO密集型
    • 外边限制
    • 锁竞争

    五、减少上下文切换开销

    日志记录的例子:
    如果直接由日志的操作线程进行日志的记录,会执行写得IO操作,从而发生阻塞,进行一次线程上下文切换。
    如果将IO操作从处理请求的线程中分离出来,处理线程只需将日志对象添加到队列中即可,从而避免线程切换。

    相关文章

      网友评论

        本文标题:详解Java并发的性能与可伸缩性

        本文链接:https://www.haomeiwen.com/subject/yahusctx.html