前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java线程实现

Java线程实现

作者头像
shysh95
发布2021-04-02 08:31:31
5030
发布2021-04-02 08:31:31
举报
文章被收录于专栏:shysh95shysh95

摘要

由于Java的并发和线程息息相关,我们今天看一下线程的实现方式,通用的线程实现方式有:

  • 使用内核线程实现
  • 使用用户线程实现
  • 使用用户线程和轻量级进程实现
  • Java线程实现

1. 内核线程

内核线程(KLT)其实就是直接由操作系统内核支持的线程,这种线程由内核完成切换。内核通过调度器对线程进行调度,将线程映射到处理器上。

在我们程序的实际使用中,不会直接去使用内核线程,而是使用内核线程的一种高级接口——轻量级进程(LWP),轻量级进程就属于我们常说的线程。轻量级进程和内核线程是1:1的关系。

由于内核线程的支持,每一个轻量级进程都是一个可以独立的调用单元,由于轻量级进程基于内核线程实现,内核线程直接由操作系统控制,所以我们可以不用线程的创建、切换、调度、阻塞,几乎所有的线程操作都可以交由操作系统内处理。

轻量级线程的缺点就是,我们的操作系统如果要使用轻量级进程必须要进行系统调用,系统调用需要在用户态和内核态进行切换,调用代价相对较高。其次每个轻量级进程对应一个内核线程,因此会占用一定的内核资源,因此一个操作系统支持轻量级进程的数量是有限的。

2. 用户线程

用户线程指的是完全建立在用户空间的线程库上,系统内核不能感知线程的存在。用户线程的所有操作都在用户态中完成,不需要内核的帮助。

用户线程的优点是不需要进行系统调用,调用代价低,缺点就是用户需要自己维护线程的创建、调度、同步、阻塞等操作,实现代价相对较高。

3. 用户线程+轻量级进程

用户线程+轻量级进程就是采用了上述两种实现的结合,通过这种结合我们可以取其精华去其糟粕。

首先用户线程是完全建立用户空间,用户线程的创建、切换调用代价较低,并且可以支持大规模的并发。

轻量级进程是用户线程和内核线程的之间的桥梁,通过轻量级进程,我们可以使用内核提供的线程调度功能和处理器映射(实现代价相对较高的操作)。在这种混合模式中,用户线程和轻量级进程的比例关系为N:M。

4. Java线程实现

Java线程的实现方式就是采用用户线程+轻量级进程混合的模式,Java线程和轻量级进程的比例关系为1:1,至于为什么是1:1,我们可以分析一下:

我们在使用Java的Thread时,会调用start方法开启一个线程。

代码语言:javascript
复制
    public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

    private native void start0();

在start方法中有个关键的方法就是start0(),然后该方法是个native方法,这时候我们就需要看一下JDK的源码实现了,关于这个start0方法是在源码文件./jdk/src/share/native/java/lang.Thread.c中,如下图:

我们可以看到,start0方法实际上执行的JVM_StartThread方法,该方法所在的文件是./hotspot/src/share/vm/prims/jvm.cpp。

上图中JVM_StartThread方法中我们会new一个JavaThread,然后我们看一下这个JavaThread的实现, JavaThread的类定义在./hotspot/src/share/vm/runtime/thread.cpp中,如下图:

os::create_thread(this, thr_type, stack_sz);这里就是各个操作系统去创建线程了,这里我们假设我们的操作系统是linux操作系统,create_thread的方法存储在,./hotspot/src/os/linux/vm/os_linux.cpp中,linux中的线程创建方式是pthread,在create_thread方法中最终会有如下代码,完成轻量级进程的创建,如下:

通过上述分析,我们可以看到,在Java中每创建一个线程,我们变会创建一个轻量级进程,所以Java中的用户线程和轻量级进程为1:1。

本期的Java线程实现介绍到这,我是shysh95,顺手关注+在看,我们下期再见!!!

往期推荐

Java内存模型(可见性有序性)

Java内存模型

Java学习路线

JIT即时编译器(C1和C2)

JIT即时编译(基础概念)

Java泛型擦除

Java编译原理(javac)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员修炼笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档