Java 思考题:Java程序设计中创建的线程属于哪种实现方式?为什么进程切换的开销比线程切换大呢?

思考题 by jwk

image-20220317145651910

思考题(一):

1、结论

Q:Java程序设计中创建的线程属于哪种实现方式?

A:Java的线程是映射到操作系统的原生线程之上的,在 Linux 和 windows 使用的是内核级线程。

Java线程在 JDK1.2之前,是基于称为 “绿色线程“(Green Threads) 的用户线程实现的

而在 JDK1.2 中,线程模型替换为基于操作系统原生线程模型来实现。

JVM 没有限定Java线程需要使用哪种线程模型来实现,JVM 只是封装了底层操作系统的差异,而不同的操作系统可能使用不同的线程模型,例如 Linux 和 windows 使用了一对一模型,solaris 和unix 某些版本可能使用多对多模型。所以一谈到 Java 语言的多线程模型,需要针对具体 JVM 实现。

比如 Sun JDK 1.2 开始,线程模型都是基于操作系统原生线程模型来实现,它的 Window 版和 Linux 版都是使用系统的1:1的线程模型实现的。

image-20220317150439635

轻量级进程与内核线程之间1:1的关系

进程与用户线程之间1:N的关系

用户线程与轻量级进程之间M:N的关系

image-20220317150251326

2、证据

image-20220317152119957

image-20220317153118656

image-20220317152618670

3、实验

image-20220317153402404

image-20220317153643345

image-20220317154845433

image-20220317155032533

不可以直接看总线程数!!!没法控制后台程序,服务、网络啊。没办法保证线程的销毁和创建,所以是不准确的。就算按照一对一的,也不是说三个进程就是三个进程。还有销毁的进程等等一系列的进程。

思考题(二):

1、用户模式不用进程切换

image-20220317155615784

image-20220317160242302

2、不经历虚拟地址到物理地址的转化

img

进程切换会涉及到虚拟地址空间的切换,而这正是导致进程切换比线程切换慢的原因所在

访问页表(内存)次数太多导致其成为了操作系统地一个性能瓶颈,转换检测缓冲区(Translation Lookaside Buffer,TLB)应运而生,也称为快表

由于进程切换会涉及到虚拟地址空间的切换,这就导致内存中的页表也需要进行切换,一个进程对应一个页表是不假,但是 CPU 中的 TLB 只有一个,页表切换后这个 TLB 就失效了。这样,TLB 在一段时间内肯定是无法被命中的,操作系统就必须去访问内存,那么虚拟地址转换为物理地址就会变慢,表现出来的就是程序运行会变慢。

而线程切换呢,由于不涉及虚拟地址空间的切换,所以也就不存在这个问题了。

简单的分析的话:

  1. 进程包含的内容比较多,线程只包含自己的上下文等信息,不包括资源信息,切换时比较快;
  2. 进程切换涉及进程地址空间切换,如果一个进程中的多个线程间切换,就不用切换地址空间。

备注:

参考上方 zero copy 图,可更好理解用户态和内核态

鸣谢:

参考书籍

posted @ 2022-03-17 16:27  季文康  阅读(207)  评论(0编辑  收藏  举报