15 | 多线程调优(上):哪些操作导致了上下文切换?
该思维导图由 AI 生成,仅供参考
初识上下文切换
- 深入了解
- 翻译
- 解释
- 总结
本文深入探讨了多线程上下文切换的原因和影响。作者首先介绍了上下文切换的概念,并指出在多核处理器时代,上下文切换变得更加频繁,存在跨核切换更加昂贵。文章详细分析了多线程上下文切换的诱因,包括自发性和非自发性上下文切换,以及虚拟机垃圾回收可能导致的上下文切换。通过代码对比和数据分析,阐述了上下文切换对系统性能的影响,强调了单线程在某些情况下的优势。此外,还介绍了在Linux和Windows系统下监测上下文切换的方法,并总结了上下文切换可能带来的系统开销。最后,提出了思考题,引发读者对多线程中使用Synchronized可能导致的进程间上下文切换的思考。 总的来说,本文通过实例和技术原理深入浅出地介绍了多线程上下文切换的相关内容,对于理解并发编程中的性能问题具有一定的参考价值。
《Java 性能调优实战》,新⼈⾸单¥59
全部留言(48)
- 最新
- 精选
- 晓杰锁的竞争太激烈会导致锁升级为重量级锁,未抢到锁的线程会进入monitor,而monitor依赖于底层操作系统的mutex lock,获取锁时会发生用户态和内核态之间的切换,所以会发生进程间的上下文切换。
作者回复: 对的
2019-06-2586 - 尔冬橙老师,网上有个争议,sleep会不会释放cpu时间片?
作者回复: sleep不会释放锁资源,wait则会,但两者都会从running状态中走出,也就是不再占用CPU资源。
2019-09-2036 - 李博如果Synchronized块中包含io操作或者大量的内存分配时,可能会导致进程IO等待或者内存不足。进一步会导致操作系统进行进程切换,等待系统资源满足时在切换到当前进程。 不知道理解的对不对?
作者回复: 进程上下文切换,是指用户态和内核态的来回切换。我们知道,如果一旦Synchronized锁资源竞争激烈,线程将会被阻塞,阻塞的线程将会从用户态调用内核态,尝试获取mutex,这个过程就是进程上下文切换。
2019-06-22328 - 内卷毁灭世界进程的上下文切换是指从一个进程切换到另一个进程运行。用户态到内核态为什么也属于进程上下文切换?从哪个进程切换到哪个进程了?
作者回复: 在linux操作系统中,进程的运行空间一般分为用户态和内核态,用户态空间一般是进程应用运行空间,而内核态空间一般是指应用需要调用系统资源,应用不能再用户态空间直接调用系统资源,需要通过内核态来系统系统资源。 所以进程在用户态和内核态两个直接相互切换,就称之为进程上下文切换。
2019-11-2517 - 钱课后思考及问题 本文核心观点 1:线程上下文切换指啥? 线程上下文切换指一个线程被暂停剥夺对CPU的使用权,另外一个线程被选中开始或者继续在CPU中运行的过程。 2:线程上文切换的问题? 上下文切换会导致额外的性能开销,因为一个线程正在CPU上执行需要停下来换另外一个线程来执行,需要做许多的事情。 3:上下文切换的性能开销花费在哪里啦? 操作系统保存和恢复上下文; 调度器进行线程调度; 处理器高速缓存重新加载; 上下文切换也可能导致整个高速缓存区被冲刷,从而带来时间开销。 4:上下文切换的分类? 上下文切换分为进程上下文切换和线程上下文切换,这是站在操作系统的层面来讲的,站在CPU的角度,它不知道什么进程、线程之类的东西,他只需要知道怎么取指令怎么执行就行啦! 5:上下文切换的发送场景? 上下文切换分为两种,一是自发上下文切换,另一个是非自己上下文切换。 6:啥是自发上下文切换?怎么触发? 自发性上下文切换指线程由 Java 程序调用导致切出,在多线程编程中,执行调用以下方法或关键字,常常就会引发自发性上下文切换。 sleep() wait() yield() join() park() synchronized lock 7:啥是非自发上下文切换?怎么触发? 非自发性上下文切换指线程由于调度器的原因被迫切出。常见的有:线程被分配的时间片用完,虚拟机垃圾回收导致或者执行优先级的问题导致。 8:在多线程中使用 Synchronized 会发生进程间的上下文切换,具体的发生环节如下(声明:答案我没想到,参考评论区老师的回答)? 当升级到重量级锁后,线程竞争锁资源,将会进入等待队列中,并在等待队列中不断尝试获取锁资源。每次去获取锁资源,都需要通过系统调底层操作系统申请获取Mutex Lock,这个过程就是一次用户态和内核态的切换。 有个疑问,老师具体没讲什么是进程的上下文切换?什么是线程的上下文切换?评论区中又特意强调进程间的上下文切换指用户态和内核态之间的切换。那线程间的切换指什么?线程一直在内核态空间中,只是切出了CPU是吗?
作者回复: 进程间的上下文切换因为是用户态和内核态之间的切换,需要消耗更多的资源,例如,寄存器中的内容切换出,缓存的刷新等,而线程间的上下文切换是用户态的线程切换,由于是同一个虚拟内存,消耗资源相对较少。
2019-09-0912 - 老杨同志使用Synchronized获得锁失败,进入等待队列会发生上下文切换。如果竞争锁时锁是其他线程的偏向锁,需要降级,这是需要stop the world也会发生上下文切换
作者回复: 理解正确~
2019-06-22310 - 尔冬橙老师,可以讲下进程从用户态到内核态为什么就发生了上下问切换呢
作者回复: Java应用进程里面执行的代码则是属于用户态,而系统内核代码执行则属于内核态,假设我们一个同步锁的执行,首先会在Java应用程序中执行,之后需要切换到系统内核中去获取mutex,在切换的时候,需要将原来用户态的执行指令与内核执行指令相互切换,此时CPU资源也会发生切出切入。
2019-09-208 - Liam老师好,请教一个问题: 1 非自发场景中,cpu time slice 用完后切换线程,此时被暂停线程是什么状态呢?runnable or blocked, 如果是runnable的话,是不是意味着从runnning到runnable也会导致上下文切换
作者回复: 我们可以调用yield,线程可以从runnning到runnable,我们可以手动编程试试,看看cs是不是增加了。 yield也会导致上下文切换的。
2019-06-226 - 吴青老师,你是不是把waiting和timed_waiting状态漏了
作者回复: 这里指的是系统中线程的五个基本状态,waiting以及timed_waiting属于阻塞,这里的阻塞包括争用锁导致的阻塞blocked状态、调用wait(timeout)导致的timed_waiting状态以及调用wait()导致的waiting状态。
2019-11-245 - 欧星星使用Synchronized在锁获取的时候会发生CPU上下文切换,多线程本身也会有上下文切换,这样就会多一次切换,是这样吗?
作者回复: Synchronized在轻量级锁之前,锁资源竞争产生的是线程上下文切换,一旦升级到重量级锁,就会产生进程上下文切换。
2019-06-225