深度解密:Java与线程的关系
并发不一定要依赖多线程(如PHP的多进程并发),但在Java中谈论并发,大多数都与线程脱不开关系。
线程的实现
线程是CPU调度的基本单位,Thread类与大部分的Java API有显著的差别,它的所有关键方法都是声明为Native的,意味着这个方法没有使用或无法使用平台无关的手段来实现。
内核线程(Kernel-Lever Thread,KLT)
直接由操作系统内核(Kermel,下称内核)支持的线程,由内核来完成线程切换,内核通过操纵调度器(Sheduler) 对线程进行调度,并负责将线程的任务映射到各个处理器上。
每个内核线程可以视为内核的一个分身,这样OS就有能力同时处理多件事情,支持多线程的内核就叫做多线程内核(Multi-Threads Kernel )。
程序一般不会直接去使用KLT,而使用KLT的一种高级接口即轻量级进程(Light Weight Process,LWP),即我们通常意义上所讲的线程,由于每个LWP都由一个KLT支持,因此只有先支持KLT,才能有LWP。这1:1的关系称为一对一的线程模型。
局限性
由于是基于KLT实现的,所以各种线程操作,如创建、析构及同步,都需要进行系统调用。而系统调用的代价相对较高,需要在用户态和内核态中来回切换。其次,每个LWP都需要有一个KLT的支持,因此LWP要消耗一定的内核资源(如KLT的栈空间),因此一个系统支持LWP的数量是有限的。
用户线程
创建,切换和调度各种细节都需要考虑,实现及其困难,已被java、ruby等语言放弃用户线程混合轻量级进程。
Java线程的实现
用户线程还是完全建立在用户空间中,因此用户线程的创建、切换、析构等操作依然廉价,并且可以支持大规模的用户线程并发操作系统提供支持的轻量级进程则作为用户线程和内核线程之间的桥梁,这样可以使用内核提供的线程调度功能及处理器映射,并且用户线程的系统调用要通过轻量级线程来完成,大大降低了整个进程被完全阻塞的风险。
在这种混合模式中,用户线程与轻量级进程的数量比是不定的,即为N :M 的关系许多UN1X 系列的操作系统,如Solaris、HP-UX 等都提供了N: M 的线程模型实现。
Java 线程
JDK 1.2 之前是基于称为“绿色线程”(Green-Threads )的用户线程实现,在JDK 1.2 中替换为基于操作系统原生线程模型来实现,因此,在目前的JDK 版本中,操作系统支持怎样的线程模型,在很大程度上决定了Java 虚拟机的线程是怎样映射的,这点在不同的平台上没有办法达成一致,虚拟机规范中也并未限定Java 线程需要使用哪种线程模型来实现。
线程模型只对线程的并发规模和操作成本产生影响,对Java 程序的编码和运行过程来说,这些差异都是透明的。
对于Siun JDK 来说,它的Windows 版与Linux版都是使用一对一的线程模型实现的,一条Java线程就映射到一条轻量级进程之中,因为Windows 和Linux系统提供的线程模型就是一对一的而在Solaris 平台中,由于操作系统的线程特性可以同时支持一对一(通过Bound
Threaids或Alternate Libthread实现)及多对多( 通过LWP/Thread Based Synchronization
实现) 的线程模型,因此在Solaris 版的JDK 中也对应提供了两个平台专有的虚拟桃参数:
-XX:+UseLWPSynchronization (默认值) 和-XX:+UseBoyndThreads 来明确指定虚拟机使用哪种线程模型。
Java线程调度
线程调度
系统为线程分配处理器使用权的过程,主要调度方式有两种
协同式线程调度(Cooperative Threads-Scheduling)
抢占式线程调度(Preemptive Threads-Scheduling )
使用协同式调度的多线程系统,线程执行时间由线程本身控制,线程把自己工作执行完后,要主动通知系统切换到另外一个线程上。
协同式多线程
最大好处
实现简单,而且由于线程要把自己的事情干完后才进行线程切换,切换操作对线程白己是可知的,所以没有什么线程同步的问题
坏处也很明显
线程执行时间不可控制
使用抢占式调度的多线程系统,那么每个线程将由系统来分配执行时间,线程的切换不由线程本身决定,在这种实现线程调度的方式下,线程执行时间系统可控的Java使用的线程调度方式就是抢占式调度虽然Java线程调度是系统自动完成的,但是我们还是可“建议”系统给某些线程多分配一点执行时间,可以通过设置线程优先级来完成。Java 语言一共设置了10个级别的线程优先级(Thread.MIN_PRIORITY 至Thread.MAX_PRIORITY ),在两个线程同时处于Ready 状态时,优先级越高的线程越容易被系统选择执行。
Java 的线程是通过映射到系统的原生线程上来实现的,所以线程调度最终还是取决于OS,虽然现在很多OS都提供线程优先级的概念,但是并不见得能与Java线程的优先级对应,如Solaris中有2147483648 (232 )种优先级,但Windows中就只有7种,比Java 线程优先级多的系统还好说,中间留下一点空位就可以了,但比Java线程优先级少的系统,就不得不出现几个优先级相同的情况了,不仅仅是说在一些平台上不同的优先级实际会变得相同这一点,还有其他情况让我们不能太依赖优先级:优先级可能会被系统自行改变。
例如,在Windows 系统中存在一个称为“优先级推进器”(Priority Boosting,当然它可以被
关闭掉) 的功能,它的大致作用就是当系统发现一个线程执行得特别“勤奋努力”的话,可能会越过线程优先级去为它分配执行时间。因此,我们不能在程序中通过优先级完全准确地判断一组状态都为Ready 的线程将会先执行哪一个。
深度解密:Java与线程的关系的更多相关文章
- Java并发指南12:深度解读 java 线程池设计思想及源码实现
深度解读 java 线程池设计思想及源码实现 转自 https://javadoop.com/2017/09/05/java-thread-pool/hmsr=toutiao.io&utm_ ...
- 深度分析 Java 的枚举类型:枚举的线程安全性及序列化问题(转)
写在前面: Java SE5 提供了一种新的类型 Java的枚举类型,关键字 enum 可以将一组具名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用,这是一种非常有用的功能 ...
- 深度分析Java的枚举类型—-枚举的线程安全性及序列化问题
原文:深度分析Java的枚举类型--枚举的线程安全性及序列化问题 枚举是如何保证线程安全的 要想看源码,首先得有一个类吧,那么枚举类型到底是什么类呢?是enum吗?答案很明显不是,enum就和clas ...
- 【转载】深度解读 java 线程池设计思想及源码实现
总览 开篇来一些废话.下图是 java 线程池几个相关类的继承结构: 先简单说说这个继承结构,Executor 位于最顶层,也是最简单的,就一个 execute(Runnable runnable) ...
- 不为人知的网络编程(八):从数据传输层深度解密HTTP
1.引言 在文章<理论联系实际:Wireshark抓包分析TCP 3次握手.4次挥手过程>中,我们学会了用wireshark来分析TCP的“三次握手,四次挥手”,非常好用.这就是传说中的锤 ...
- 【JVM】深度分析Java的ClassLoader机制(源码级别)
原文:深度分析Java的ClassLoader机制(源码级别) 为了更好的理解类的加载机制,我们来深入研究一下ClassLoader和他的loadClass()方法. 源码分析 public abst ...
- 深度解密Go语言之channel
目录 并发模型 并发与并行 什么是 CSP 什么是 channel channel 实现 CSP 为什么要 channel channel 实现原理 数据结构 创建 接收 发送 关闭 channel ...
- Java设计模式——线程安全的单件模式
单件模式,也称单例模式,用以创建独一无二的.只能有一个实例的对象. 单件模式的类图是所有模式的类图中最简单的--只有一个类.尽管从类设计的视角来看单件模式很简单,但是实现上还是会遇到一些问题,本文着重 ...
- 深入理解Java之线程池
原作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本文归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...
随机推荐
- python-内置函数-compile,eval,exec
#将字符串,编译成python代码 compile()#执行,有返回值,执行表达式并获取结果 eval()#执行python代码,无返回值,接收:代码或者字符串 exec() s = "pr ...
- 【Azure 环境】基于Azure搭建企业级内部站点, 配置私有域名访问的详细教程 (含演示动画)
前言 在Azure中,可以通过App Service快速部署,构建自定义站点(PaaS服务).默认情况下,这些站点被访问URL都是面向公网,通过公网进行解析.为了最好的安全保障,是否可以有一种功能实现 ...
- Dom树,什么是dom树?
相信很多初学前端的小伙伴,学了html,css,js之后,欣喜之余还有一丝小傲娇,没有想到那些大佬们口中又 提到了DOM树.你两眼一抹黑,年轻人总是要接受社会的爱(du)护(da). DOM 是 Do ...
- C++ primer plus读书笔记——第7章 函数——C++的编程模块
第7章 函数--C++的编程模块 1. 函数的返回类型不能是数组,但可以是其他任何一种类型,甚至可以是结构和对象.有趣的是,C++函数不能直接返回数组,但可以将数组作为结构或对象的组成部分来返回. 2 ...
- [JavaScript之BOM与DOM]
[JavaScript之BOM与DOM] BOM(Browser Object Model)是指浏览器对象模型,它使 JavaScript 有能力与浏览器进行"对话". DOM ( ...
- 匿名函数lambda / map()方法
lambda一般配合其他方法使用,一般使用在只用过一次就不用的函数,那就没必要特意去定义 lambda能支持的最复杂的语句就是三元运算 例如: lambda x,y: x*y if x < y ...
- 风变编程(Python自学笔记)第12关-我们都是中国人
1.类的个例叫做实例:类,是对某个群体的统称(类是某个特定的群体),实例是群体中某个具体的个体. 2.Python中的对象等于类和实例的集合. 3. 类的创建:class+类名+冒号,后面语句要缩进. ...
- ES6中的Set和Map对象数据结构
set对象数据结构 构建某一类型的对象 -对象的实例化 let arr = [1, 2, 3, 3, 4, 5] let rec = new Set(arr)//可以传参数,数组或者对象 consol ...
- git 速度慢问题解决
使用VPN上网后,如果git下载速度还是很慢说明没有正确设置代理 查看你的代理模式是否是pac代理,如果是改成全局或者Http代理,pac代理会选择性的代理网站,可能会略过某些网站. 如果还是比较慢则 ...
- Spring IoC容器 XML 配置与加载
IoC 容器 XML 配置文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=&qu ...