JVM中的线程模型是用户级的么?

看了一篇文章说JVM的线程模型是用户级线程,对于OS来说JVM就是一个进程,但是用户级线程的问题就是只要一个线程产生了一次系统调用,比如I/O中断,那同一进程内的其他线程都会停止,是这样的么?
关注者
101
被浏览
4571
楼主的问题只能针对具体JVM实现来回答,在JVM规范里是没有规定的——具体实现用1:1(内核线程)、N:1(用户态线程)、M:N(混合)模型的任何一种都完全OK。Java并不暴露出不同线程模型的区别,上层应用是感知不到差异的(只是性能特性会不太一样…)

Java SE最常用的JVM是Oracle/Sun研发的HotSpot VM。在这个JVM的较新版本所支持的所有平台上,它都是使用1:1线程模型的——除了Solaris之外,它是个特例。

这是HotSpot VM在Solaris上所支持的线程模型:Java(TM) and Solaris(TM) Threading
<- 可以看到HotSpot VM在Solaris上支持M:N和1:1模型。当前默认是用1:1模型。

前面的回答里大家提到的“肯定不是用户态线程,不然怎么利用多核”、“多线程优势何在”,这些问题在使用N:1、M:N模型的JVM实现上确实存在。

我喜欢用的一个例子是Oracle/Sun的另一个JVM实现,用于Java ME CLDC的CLDC HotSpot Implementation(CLDC-HI)。它支持两种线程模型,默认使用N:1线程模型,所有Java线程都映射到一个内核线程上,是典型的用户态线程模型;它也可以使用一种特殊的混合模型,Java线程仍然全部映射到一个内核线程上,但当Java线程要执行一个阻塞调用时,CLDC-HI会为该调用单独开一个内核线程,并且调度执行其它Java线程,等到那个阻塞调用完成之后再重新调度之前的Java线程继续执行。
有权限访问到的同学可以去读读CLDC HotSpot Implementation Architecture Guide(百度文库有对应CLDC-HI 2.0的版本:CLDC-Hotspot-Architecture_百度文库),里面的第5章介绍了CLDC-HI的线程模型,下面引用部分内容过来:

The system has two distinct threading models. The simplest and preferred model supports LWTs (light weight threads). In this model, CLDC HotSpot Implementation implements all LWTs on a single native OS thread. LWTs are essentially co-routines created and scheduled by the virtual machine. This is transparent at the Java runtime environment level.
...
A special style of handling threading might be preferable in some ports. This style relies on the availability of native thread support in the target platform OS. It is called hybrid threading, ...
然后在另一份文档,CLDC HotSpot Implementation Porting Guide的第4章里介绍了如何移植CLDC-HI的线程系统到别的平台。elastos.org有一份CLDC-HI 1.1.3版本的:elastos.org/elorg_files。同样摘抄一小段描述出来:
Non-blocking scheduling - The native method de-schedules its lightweight
thread (LWT) until another part of the virtual machine determines that the native
method can be executed without blocking. Then the native method is reentered to
proceed with the given problematic call that is now guaranteed to be of
sufficiently short duration.
Hybrid threading - The native method de-schedules its LWT after delegating the
task to an OS thread to execute the given blocking call. When this OS thread,
which is truly concurrent to the rest of the virtual machine, completes the call, it
causes the LWT to resume. The LWT then reenters the native method to fetch the
results of the blocking call.
...
If you port to another platform, it might be the case that only one of the styles can be
implemented. Non-blocking scheduling depends on the existence of functions that
can determine whether a subsequent call would block. Take for example the
select() function for BSD sockets that can be used to determine whether a socket
is ready for a non-blocking data transmission call. Hybrid threading requires that
several OS threads are available and that all the blocking OS calls that you want to
employ are reentrant.

可见,使用用户态线程是会有潜在的并行瓶颈问题,但也有(一定程度的)解决办法。