首页 归档 关于 learn love 工具

Java线程创建过程中的各种细节

今天咱们来谈谈Java线程创建的一些细节问题:

  1. Java线程是如何与OS线程建立联系的
  2. Java线程与OS线程共用一套线程状态吗
  3. Java线程是如何做到创建与启动分开的
  4. Java线程在JVM层面为什么要有JavaThread与OSThread
  5. Java线程为什么设计的时候要将创建与启动分开

先把这五个问题搞明白吧,其他的后面的文章再分享。本篇文章的观点都聚焦于Linux平台,不适用于所有平台。因为不同OS,底层差异还是挺大的。

Linux线程创建

线程能力是操作系统才有的,固Java的线程机制一定是基于OS的线程机制实现的,加上些许JVM自身的考虑在其中。这些考虑在哪能看到?JSR规范中。

上一段Linux平台下创建线程的代码

这样创建出来的线程,一般称为原生线程,或native thread。Java的线程实现其实就是将Linux下的线程机制基于JSR规范进行设计重组。如果我们了解Linux的线程机制,并搞明白了JVM是如何进行设计重组的。那么,Java的多线程,我们就算真正学明白了。

可以发现,跟Java创建线程明显不同的是:原生线程创建与运行是一体的,即线程创建完毕马上就运行。而Java中创建归创建,调用start线程才运行。

Java线程与原生线程之间是这样的关系:JavaThread->OSThread->native thread。后面会结合hotspot源码细讲。

Java线程创建

上一段创建Java线程的代码

从研究问题的角度,这段我们习以为常的代码要分成两部分来看:一、创建一个Java对象。注意,这一步只是单纯地创建一个Java对象,并没有什么特殊处理在里面。二、调用start方法让线程运行。我们上面提的几个问题,所有的秘密都在这一步中。接下来我结合hotspot源码将上面几个问题的答案分享给大家。

在 Java 中创建一个线程分为两步:

Thread thread = new Thread(() -> ...);
thread.start();

其中 new 操作只是调用了 Thread::init 方法做了一些初始化的操作,此时还没有跟操作系统交互。Java 的线程是直接与操作系统线程是 1:1 的,在 Thread::start 时会调用操作系统的 API 创建 native thread(例如 Linux 下会调用 glibc 的 pthread_create 创建)。

OS线程属性

操作系统(OS)线程的分离属性(detach)和连接(join)属性分别对应线程结束后,资源释放的操作.

  • join属性的线程,需要同一个进程中的其他线程,获取线程终止的状态,并释放资源.
  • detach属性的线程,在线程结束后,由系统释放资源.

os线程创建的默认属性为joinable,在Java中通过new Thread创建的线程于OS而言都是分离线程。那么这个时候Java如何获取线程的执行结果呢?答案就是通过修改共享内存上变量的值。

我们都知道Java创建的线程其实是调用的操作系统的能力,那么从java中的线程对象到OS的线程对象,依次经过以下对应关系,而Linux线程操作的结果,就会存储在JVM的Java Thread对象中的_VM_result_2中,这个对象就可以理解为共享内存

参考

https://developer.aliyun.com/article/922947
https://www.ninan.life/%E6%89%8B%E5%86%99JVM%E7%AC%94%E8%AE%B0/
https://lotabout.me/books/Java-Concurrency/Cost-of-Thread/index.html