zoukankan      html  css  js  c++  java
  • 多线程性能与可伸缩性

    1 单线程程序不需要线程调度也不需要同步开销,而且不需要使用锁来保证数据结构的一致性。在多线程的调度和协调中都需要一定的性能开销。对于为了性能而引入多线程的程序,并行带来的性能提升必须要超过并发导致的开销。

    2 上下文切换

    如果可运行的线程数大于 CPU 的数量,那么操作系统最终会将某个正在运行的线程调度出来,从而使其他线程能够使用 CPU。这将导致一次上下文切换,在这个过程中将保存当前运行线程的执行上下文,并将新调度进来的线程执行上下文设置为当前上下文。

    切换上下文的开销:线程调度过程中需要访问由操作系统和JVM 共享的数据结构。应用程序、操作系统和JVM都是用一组相同的CPU。jvm 和 操作系统使用越多的cpu时钟周期,应用程序可用的 cpu 周期就越少。而线程切换开销不仅包含 jvm 和 操作系统开销,当一个线程切换进来后它所需要的数据可能不在当前处理器的本地缓存,因此上下文切换将导致一些缓存的缺失,因而线程在首次调度时会更加缓慢。

    当线程由于等待某个发生竞争的锁而被阻塞时,JVM 通常会将这个线程挂起,并允许他被交换出去。阻塞包括:阻塞IO、等待获取发生竞争的锁、条件变量上的等待。

    如国内和执行时间占用率较高(超过10%),就表示调度活动发生的很频繁,这很可能是 IO 或竞争锁导致的阻塞引起的。

    3 内存同步

    在评估同步操作带来的性能影响时,区分竞争同步和无竞争同步非常重要。

    例如方法的代码片段

    public String getnames() {
            List<String> stooges = new Vector<>();
            stooges.add("Moe");
            stooges.add("Larry");
            stooges.add("Curly");
            return stooges.toString();
        }

    该方法至少会获得释放4次锁。对于 list 的唯一引用就是局部变量 stooges ,并且封闭在栈中的变量都会自动成为线程本地变量。一些智能的运行时编译器会分析这些调用,将去掉这4次无竞争的锁获取操作。

    某个线程同步可能会影响其他线程的性能,因为同步会增加共享内存总线上的通信量,总线的带宽是一定的,并且所有处理器都将共享这条总线。如果有多个线程竞争同步总线带宽,那么所有使用同步的线程都会受到影响。

    4 在并发程序中,通常更多地将侧重点放在吞吐量和可伸缩性上。

    提升程序的可伸缩性方法:

    • 减少锁的持有时间
    • 降低锁的粒度
    • 采用非独占的锁或非阻塞的锁来代替独占锁。

    5 评价并行性的指标

    吞吐量:指一组并发任务中已完成任务所占的比例

    响应性:指请求从发出到完成之间的时间

    可伸缩性:指在增加更多资源的情况下(通常指CPU),吞吐量的提升情况。

  • 相关阅读:
    C#音频截取与原文匹配2:使用ffmpeg处理音频文件
    C#音频截取与原文匹配
    Redis报错: StackExchange.Redis.RedisServerException: Endpoint 39.105.22.111:7200 serving hashslot 12448 is not reachable at this point of time.
    kafka单机安装部署
    zookeeper部署
    mysql-5.7.15编译安装
    centos7安装sqlserver
    redisearch模块安装
    yum安装软件后保留rpm包
    shell读取配置文件
  • 原文地址:https://www.cnblogs.com/zhaopengcheng/p/10095002.html
Copyright © 2011-2022 走看看