Java多线程 多线程性能问题--上下文切换,内存同步

文章目录

      • 多线程性能问题--上下文切换,内存同步
        • 性能问题有哪些体现, 什么是性能问题
      • 为什么多线程会带来性能问题

多线程性能问题–上下文切换,内存同步

性能问题有哪些体现, 什么是性能问题

在单线程的情况, 不需要考虑多线程的调度, 上下文切换的开销 , 不需要用锁, 并发数据结构. 但是多线程的情况,虽然带来了效率的提高, 也带来了安全性的问题, 活跃性问题, 但同时也会带来性能问题.
性能问题的体现有多种方面, 例如接口响应时间慢, 吞吐量降低, 内存和cpu占用高. 并且, 性能问题如果只是通过提高硬件配置的方式, 也是治标不治本的. 性能问题虽然不会带来结果的错误, 但是极大的影响了用户的使用体验.

为什么多线程会带来性能问题

主要是两方面.
调度原因与协作原因.

  • 调度: 上下文切换. 当可以运行的线程,超过CPU的数量 , 操作系统就需要调度线程了, 以便让每个系统都有机会运行.
    上下文切换的场景: 某个线程调用了sleep方法, 此时就把cpu资源调度给了其他线程, 那么此时就叫线程的上下文切换. 上下文切换带来的开销是极大的. 可能比运行线程时带来的开销还要大, 通常上下文的切换, 会消耗5千到1万的时钟周期, 大约是几微秒, 这对于cpu而言是很大的开销了.
    上下文:主要是和程序计数器,寄存器等相关的. 一次上下文切换包含的活动: 挂起一个线程, 把线程的状态, 存在内存中的某处. 记录执行到哪一步了 , 以便于线程切换回来后, 能够继续在被切换之前的地方继续执行任务.

  • 调度: 缓存开销 : 对于代码中的一些经常用到的变量cpu是有缓存的, 有利于加快运行. 但是一旦进行线程的切换, 缓存就失效了,也会导致程序运行变慢. 为了防止线程切换带来的缓存开销问题, 通常cpu会设置最小的线程切换的时间.

  • 调度: 何时导致密集的上下文切换 : 会根据程序的不同, 应用场景的不同而有不同. 比如频繁的抢锁, 频繁的IO阻塞, 此时就会带来大量的上下文切换.

  • 协作 :内存同步 . 编译器会对程序进行优化 , 例如指令重排序, 锁优化. 对于CPU是有主内存和各自的缓存的, 使用缓存可以大大的增加 程序的执行速度, 因为不必要和主存进行同步, 但是如果使用 synchronized volatile 等关键字可能会导致缓存的失效, 这样也会导致内存同步的问题带来开销. 因为无法在cpu 的内部进行 进一步的缓存,只能使用主内存, 降低了效率.

你可能感兴趣的:(Java多线程基础与核心)