Java多线程模型及实现方式

为什么要多线程并发?

并发处理的广泛应用是使得阿姆达尔定律代替摩尔定律成为计算机发展源动力的根本原因,也是人类压榨计算机运算能力的最强有力武器。

阿姆达尔(Amdahl)定律通过系统中并行化与串行化的比重来描述多个处理器系统能获得的运算加速能力。摩尔定律则用于描述处理器晶体管数量与运行效率之间的发展关系。这两个定律的更替代表了近年来硬件发展从追求处理器频率到追求多核心并行处理的发展过程。

 

并发并不一定要依赖多线程,比如“世界上最好的开发语言”PHP就是用多进程实现并发,那么Java线程底层又是如何实现的呢?耐心看到最后哦。

线程是CPU调度的基本单位,主流操作系统都提供了线程实现,Java语言则提供了在不同硬件和操作系统平台下对线程的统一处理(这也是Java敢声称一次编译到处运行的底气之一),Java里面线程对象是Thread类产生的,Thread类的关键方法都是Native的,也就是说这些方法都是针对特定的操作系统去特定实现的。

 

实现线程主要有三种方式:

1)使用内核线程实现:

内核线程就是直接由操作系统支持的线程,这种线程由内核来完成线程的切换,内核通过操纵调度器对线程进行调度,并负责将线程的任务映射到各个处理器上,每个内核线程可以视为内核的一个分身,这样操作系统就有能力同时处理多件事情,支持多线程的内核叫多线程内核。

然而程序一般不会直接去使用内核线程,而是去使用内核线程的一种高级接口---轻量级进程。轻量级进程就是我们通常意义上讲的线程,由于每个轻量级进程都有一个内核线程支持,因此只有线支持内核进程,才能支持轻量级进程。这种轻量级进程与内核线程之间是一比一存在的。

轻量级进程可以很好的配合处理器调度,但是也是有一些局限性的,一是由于是基于内核线程实现,因此创建、析构、同步等都需要进行系统调用,而系统调用的代价相对高,需要在用户态和内核态来回切换。二是一个操作系统支持的内核线程是有限的也就造成支持轻量级进程也是有限的。

 

2)使用用户线程实现

可以认为,一个线程只要不是内核线程,那就是用户线程。用户线程的创建,销毁,同步等完全在用户态中完成,不需要内核的帮助,因此操作是非常快且低消耗的,也可以支持更大规模的线程数量,部分高性能数据库就是通过用户线程实现的。这种进程与用户线程之间的关系为1:N的关系成为一对多线程模型。

但是用户线程由于没有内核线程的支持,因此所有的线程操作都需要用户程序自己处理。Java,Ruby等语言都曾经使用过用户线程,最终又都放弃了它,可见,它也并不是好的方案。

 

3)使用用户线程加轻量级进程混合实现

用户线程还是完全建立在用户空间中,因此用户线程的创建,切换,析构等操作依然廉价,并且可以支持大规模的用户线程并发。而操作系统提供支持的轻量级进程则作为用户线程和内核之间的桥梁,这样可以使用内核提供的线程调度功能及处理器映射,并且用户线程的系统调用要通过轻量级进程来完成,大大降低了整个进程被完全阻塞的风险。这种混合模式下,用户线程和轻量级进程的数量比是不确定的,即为N:M,这种就是多对多的线程模型。

 

4)Java线程的实现

在JDK1.2以前,是由用户线程实现的,JDK1.2以后,线程模型替换为基于操作系统原生线程模型来实现,因此,在目前的JDK版本中,操作系统支持怎样的线程模型,在很大程度上决定了Java虚拟机的线程是怎样映射的,这点在不同平台上没法达成一致,虚拟机规范也并未要求Java一定要用哪种线程模型来实现。

对于Sun JDK来说,它的Windows版和Linux版都是使用一对一的线程模型实现的,即:一个Java线程映射到一个轻量级进程之中,因为Windows和Linux提供的线程模型就是一对一的

而在Solaris平台中,由于操作系统支持一对一和多对多的线程模型,因此在Solaris版本的JDK中也对应提供了两个平台专有的虚拟机参数来明确指定虚拟机使用哪种线程模型

原文地址:https://www.cnblogs.com/cnsec/p/13407133.html