Java线程是怎么实现run方法的执行的呢?【 多线程在JVM中的实现原理剖析】

Java线程是怎么实现run方法的执行的呢?【 多线程在JVM中的实现原理剖析】

    • 查看naive state0 方法
    • JVM_StartThread 方法
    • 创建操作系统线程
    • 操作系统线程执行

本文转载-极客时间

我们知道Java线程是通过行start()方法来启动的,线程启动后会执行run方法内的代码。
Java线程其实是“寄生”在操作系统线程上,通过操作系统的线程来实现Java线程的运行。接下来我们就深入源码来看看Java线程是怎么实现“寄生”在操作系统线程上来运行的。

package com.hero.multithreading;
public class ThreadDemo {
	public static void main(String[] args) {
		Thread thread =new Thread(()->{
			System.out.println("线程");
		});
		thread.start();
	}
}

查看naive state0 方法

从入口开始,首先我们进入到Thread类的start方法内,可以看到有一个start0()方法的调用, 这里是真正启动Java线程的地方 。
Java线程是怎么实现run方法的执行的呢?【 多线程在JVM中的实现原理剖析】_第1张图片

start0是一个 native方法, 那么start0方法是在哪里实现的呢?
在openjdk源码share\native\java\lang\Thread.c 文件中我们可以找到start0的定义,Java 线程将start0方法和真正的实现方法JVM_StartThread进行了绑定。也就是说调用start0相当与调用了JVM_StartThread方法。
Java线程是怎么实现run方法的执行的呢?【 多线程在JVM中的实现原理剖析】_第2张图片
JNINativeMethod类型的结构体变量,JNINativeMethod定义在jni.h中。定义了一个native方法和jni方法的映射关系,将Java中的native方法和JVM中真正的实现方法进行绑定。
Java线程是怎么实现run方法的执行的呢?【 多线程在JVM中的实现原理剖析】_第3张图片

那么这里就有一个问题,registerNatives方法具体是在哪里何时执行映射操作的呢?
在JVM首次加载Thread类的时候,在Thread类的静态初始化块中,调用了native registerNatives方法,它对应的Jni方法就是上面的Java_java_lang_Thread_registerNatives方法,就是在这里完成了state0和JVM_StartThread的绑定。

Java线程是怎么实现run方法的执行的呢?【 多线程在JVM中的实现原理剖析】_第4张图片

JVM_StartThread 方法

至此,我们知道执行state0方法就是执行JVM_StartThread方法,它定义在hotspot JVM源码文件src\share\vm\prims\jvm.cpp 中。

Java线程是怎么实现run方法的执行的呢?【 多线程在JVM中的实现原理剖析】_第5张图片
Java线程是怎么实现run方法的执行的呢?【 多线程在JVM中的实现原理剖析】_第6张图片

创建操作系统线程

JVM在所有的操作系统中都实现了os::create_thread,我们看linux操作系统的实现在src\os\linux\vm\os_linux.cpp 中

Java线程是怎么实现run方法的执行的呢?【 多线程在JVM中的实现原理剖析】_第7张图片

操作系统线程执行

至此一个操作系统线程创建及初始化完毕了,我们返回到步骤1.2.3中的JVM_StartThread 方法中,最后一行Thread::start(native_thread); 开始执行操作系统线程。
Java线程是怎么实现run方法的执行的呢?【 多线程在JVM中的实现原理剖析】_第8张图片
至此,操作系统线程为就绪状态,等待被CPU选中运行时,就会调用执行入口函数java_start,调用Java线程的run方法,至此Java线程也就同时运行起来了。

小结一下

  1. 线程类被JVM加载时,完成线程所有native方法和C++中的对应方法绑定。
  2. Java线程调用start方法:start方法 => native state0方法 => JVM_StartThread => 创建JavaThread::JavaThread线程
  3. 创建OS线程,并指定OS线程的运行入口:创建JavaThread::JavaThread线程 => 创建OS线程
    os::create_thread => 指定OS线程执行入口Java线程的run方法
  4. 启动OS线程:运行时会调用Java线程的run方法,至此实现了Java线程的运行。
  5. 创建线程的时候使用的是互斥锁MutexLocker操作系统(互斥量),所以说创建线程是一个性能很差的操作!

你可能感兴趣的:(java,jvm,开发语言)