前言
讲到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%哟
领取专属 10元无门槛券
私享最新 技术干货