java线程与OS线程

前言

讲到java并发,其实就是讲javaAPI.

然后如果我们要学好java并发我们要知道操作系统和硬件有关系。

下面讲解下为什么java并发会跟操作系统和硬件有关系。

线程

总所周知,java的并发的基础是线程 Thread(他其实是我们java中Object);

对于我们操作系统来说 他也有一个线程 os

java

java--------------------Thread(obj)

操作系统

os----------------------线程

那么由这一点提问

java当中的线程和操作系统的线程之间是什么关系呢?

关于操作系统中的线程

操作系统也是可以创建线成的;比如资料文件中,他是可创建多线程的。他的线程其实就是c/++ 实现的。

而他的线程跟Java之间的线程是什么关系呢?是怎么调用的呢?

很简单,看Java线程源码。通过java线程start启动,去看源码。他的主要内容的方法就是start0。我们看start0源码实现是一个native本地方。java中的native方法都是操作系统中的方法,一般都是通过C/C++ 去实现的。

如图:

图片: https://uploader.shimo.im/f/0mXfeVce2bg5vKvx.png

那么这里c跟我们的操作系统到时提什么关系,跟我们的jdk又是什么关系?

首先我们jdk是java的开发包。

jdk包含了sun公司提供的java库,除了sun公司提供的java库,同时还包含提供了C文件。这些c文件实现了两部分作用

1、实现调用操作系统函数

2、调用jvm的代码 ;这个代码就是我们的上面图所示hostpot操作系统的代码。

而我们的jdk还提供了了java.exe文件,而这些exe文件就是我们的代码编写的,这些代码扩大就是我们的项目,这个项目其实就是我们的hostpot;这这个hostpot用什么语言开发的呢?他是用C++ 开发的。

那么这里弄清楚后

这里我们来看这个start0.

他会调用一个native文件,也就是我们的c文件。但是这个c 文件他并没有直接去调用os(操作系统)函数。而是调用我们的hostpot,java虚拟机中的代码。而虚拟机代码就是我们c/c++ 写的嘛,然后由他再去调用OS函数。

那么思考一个问题:我们的start0为什么不直接通过c文件调用我们的OS函数,而是通过我们的虚拟机去调用?

因为我们java当中,比如一个线程objct对象 t;我们的线程对象有很多的API,如果我们的很多API要映射到OS当中。那么我们的C文件要忙死。比如说让一个线程睡眠,他会调用C文件。

图片: https://uploader.shimo.im/f/XvEJqpvI0DEPf4PC.png

但java怎么做的呢?

java在我们的hostpot也产生了一个对象;在源码中加javaThread;可以这么认为在C++ 会有一个类跟我们的java一模一样。所以我们操作任何javaAPI都会对应到我们可以类似看做C++ 代码里的一个类。就相当于java中的对象去操作虚拟机中的对象;而虚拟机中的对再去直接调用我们OS函数。

这么做是不是比较好的方式;想一想,我们javaAPI这么多。那么我们要在C写多少个本地文件。

这里我们要理解弄清楚start方法为什么会调用run方法?

光看C语言的源码还不行,我们还要看hostpot虚拟机的源码。我们要看hostpot内部他是怎么去通过start方法返回来怎么调用java方法的。

可以这么理解:jdk包含了,sun提供的JAVA库,C文件以及整个虚拟机源码(这里不是源代码,是编译后的,exe文件)。

结论

由上面得出一个结论:

java start 一个线程,就相当于OS 去创建一个线程。

所以java的线程和操作系统的线程是一一对应的。

那么我们搞清楚这个问题有什么用呢?

既然java线程和操作系统是一一对应的,那么java当中线程对应的机制在OS中肯定也有一套对应的机制。

所以我们要搞清楚java线程的处理机制,就要先了解OS的对应的处理机制,比如互斥锁

java 通过互斥所sync os通过Mutex种方式,也就是linux的实现方式。

所以这里也就知道,为什么我们单独写一个run方法,而不是在start里面去写去实现。因为start要去调用操作系统,所以不能在这里面去写逻辑,所以需要一个方法需要os 中c++去调用。

那么猜想:他的实现是,java通过start去调用c,然后在c中实现逻辑后,然后c通过jni 反射再去调用java,就是通过反射调用找到run方法。

总结

如果问thread 方法中的start方法是怎么调用run方法的?

start方法其实说白了就去调用start0方法,而start0就是我们本地方法,start0会去调用操作系统函数的pthread_create方法。这个创建方法会有一个传回调方法的参数,这个参数其实叫主题函数。然后这个主题函数会去通过JNI反射去调用我们java中方法。

注意:这里模拟的从java调hostpot都是对的,但是从c调用java并不是hostpot真正的实现方法,他不是通过jni反射实现的,这里只是猜想模拟实现的。hostpot真正是采用C++中的另一项技术。

(本文转载自咕泡社区:syz。专业IT技术社区,互联网人技术问答、技术文章、资料经验分享、学习交流高端论坛社区,内容涵盖Java、大数据云计算、软件测试、人工智能、web前端等热门技术领域。)

升职加薪 就来咕泡学院

戳我涨薪50%哟

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20191030A0ML7N00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券