主流操作系统的线程模型有三种:内核线程模型、用户线程模型、混合线程模型,感兴趣的可以自己查阅相关资料 HotSpot虚拟机使用的是内核线程模型(Kernel-Level Thread, KLT):由操作系统内核(Kernel,下称内核)支持的线程,这种线程由内核来完成线程切换,一个线程对应一个内核线程,注意内核线程也是进程
线程模型只是概念,具体是怎么实现的呢?如果有linux下c语言编程的经验,我们可以知道线程就是模拟的进程,试想下:如果要你来设计一个多线程模型,你会怎么做? 我们需要尽可能的把进程轻量化来实现线程,但又想到它能够做到内存共享,子进程又是需要被父进程fork出来,显然一个进程并不能做到这些,那么怎么做呢?
linux中,对上面两个进程分别称作:
上面提到了HotSpot虚拟机使用的是内核线程模型(Kernel-Level Thread, KLT),我们又做了多线程实现的分析,再来看内核线程模型,如下图所示:
内核线程模型
之前的JVM文章中也提到了,计算机实际上是没有并行的,而是每个线程(进程)抢占获得cpu的时间片,来执行一段时间后,重新竞争,所以JVM内存模型中有程序计数器,上面提到的线程的调度器也是这种机制
线程的执行时间由线程本身来控制,执行结束后需要主动通知系统切换到另外一个线程上,其危险性也很大,当一个线程陷入了死循环,那么程序会一直阻塞,可能导致系统崩溃
为了解决协同式线程调度的危险,抢占式线程调度就是时间片轮转机制,各个线程只能被动的抢占cpu时间片,抢占到了的才能执行代码,时间到了后,暂停执行,重新由各个线程竞争时间片,这种方式线程的执行时间系统是可控的,不会造成协同式线程调度一直阻塞的现象,Java使用的是抢占式线程调度
Java线程调度
Java线程是在操作系统的内核线程模型上做了进一步的封装,Java多线程特性有三个:原子性、可见性、有序性,上面我们了解到了轻量级进程中有共享的内存,来实现多线程的内存共享。而HotSpot虚拟机通过虚拟机栈来对应一个线程,在虚拟机栈中又存有一个个栈帧来对应方法,里面会通过局部变量表存储一个指针指向堆中共享的对象,但是实际操作时并不是直接使用共享内存的,而是共享内存的拷贝
这种方式被称为JMM模型,下篇文章会围绕JMM模型进行展开