【Java笔记】多线程0:JVM线程是用户态还是内核态?Java 线程与OS线程的联系

文章目录

  • JVM线程是用户态线程还是内核态线程
    • 什么是用户态线程与内核态线程
    • 绿色线程
      • 绿色线程的缺点
    • 线程映射
      • 稍微回顾下线程映射模型
      • JVM线程映射
  • 线程状态
    • 操作系统的线程状态
    • JVM的线程状态
    • JVM线程与OS线程的状态关系
  • Reference

今天复盘一下Java中,JVM线程与实际操作系统中线程的一些联系
请先思考下面问题:

JVM线程是用户态线程还是内核态线程

什么是用户态线程与内核态线程

先简单回顾下几个概念:

用户线程(User Thread):在用户空间实现的线程,不是由内核管理的线程,是由用户态的线程库来完成线程的管理;
内核线程(Kernel Thread):在内核中实现的线程,是由内核管理的线程

可能有朋友觉得,Java线程都是我们用户new出来的,应该是用户态吧?
这种感觉肯定是错的,因为用户也可以完成一些内核态操作,比如通过命令行来进行命令调用与shell脚本。

先说一下结论:早期Java的“绿色线程”是用户态线程,现在则是通过1:1线程映射模型映射到内核态线程。

绿色线程

在古早版本中(jdk1.2之前),Java的一个特大卖点就是跨平台特性,也就是那个经典口号:“Write once, run anywhere”。但那个时候有些平台还没提供本地线程的支持,无法将用户线程映射到OS线程。所以那会采用的是“绿色线程”(Green Threads),也就是在虚拟平台上模拟出“内核线程”。

而绿色线程运行在用户空间,通过第三方library或者VM进行调度,可以说属于用户态线程

绿色线程的缺点

前面说了,绿色线程无法将用户线程映射为内核线程,只是在用户空间的模拟,对于造作系统来说都属于一个进程,仅有一个并发的概念,不能发挥多核CPU的优势去实现真正并行

线程映射

稍微回顾下线程映射模型

用户态线程是可以准备好程序让内核态线程执行,因此需要一些模型来实现用户线程和内核线程的对应关系:

  • One to One:一个用户线程对应一个内核线程,一旦用户线程停止,两个线程都会离开OS
    • 缺点:
      • 操作系统限制了内核线程的数量
      • 操作系统内核线程调度时,上下文切换的开销较大(相比于其他映射模型),导致用户线程的执行效率下降
  • Many to One:多个用户线程对应一个内核线程,用户线程间的切换由用户态代码实现
    • 优点:相对一对一模型,多对一模型的线程切换速度要快许多,并且数量不受OS内核线程数的影响
    • 缺点:
      • 如果其中一个用户线程阻塞,时内核线程也随之阻塞,其他用户线程也无法执行
      • 在多处理器系统上,处理器数量的增加对多对一模型的线程性能不会有明显的增加,因为所有的用户线程都映射到一个处理器上了
  • Many to Many:多个用户线程对应到多个内核线程,内核线程数M可以小于用户态线程数N
    • 优点:(解决了前两个的缺点)
      • 一个用户线程的阻塞不会导致所有线程的阻塞
      • 对用户线程的数量没有限制,
      • 在多处理器的操作系统中,多对多模型的线程也能得到一定的性能提升,但提升的幅度不如一对一模型的高

JVM线程映射

由于绿色线程仅仅是线程概念的用户态模拟,不能并行,因此后来换成了映射的方式来将JVM线程映射到OS内核线程。

现在,每个Java线程都映射到操作系统中一个完全独立的线程(一般是One to One),其创建销毁等工作都通过内核操作完成。

线程状态

操作系统的线程状态

操作系统的线程可描述为五种状态:new、ready、run、block、end

JVM的线程状态

JVM线程可描述为六种状态,在Thread中有个枚举类型,即Thread.state:

public enum State {NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED;
}
  • NEW:即线程刚创建,但未start()启动时的状态
  • RUNNABLE:表示当前线程正在运行。此时有两种可能:
    • 就绪状态:
      • start():启动线程,进入就绪状态,等待调度程序调度
      • 当前线程sleep()结束,或是其他线程join()结束
      • yield()出让线程
    • 运行中状态:
      • 线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态(也是线程进入运行中状态的唯一方法)
  • BLOCKED:在进入synchronized关键字修饰的方法或代码块(获取锁)时的状态,阻塞等待其他线程释放锁
  • WAITING:调用一些方法后会进入或设计等待状态,比如
    • Object.wait():使当前线程处于等待状态直到另一个线程通过notify()显式唤醒它;
    • Thread.join():插队,等待线程执行完毕,底层调用的是Object实例的wait方法;
    • LockSupport.park():除非获得调用许可,否则禁用当前线程进行线程调度。
    • 处于等待状态的
  • TIMED_WAITING:与WAITING类似,但是有指定的等待时间,比如:
    • Thread.sleep(long millis):使当前线程睡眠指定时间
    • Object.wait(long timeout):线程休眠指定时间,等待期间可以通过notify()/notifyAll()唤醒;
    • Thread.join(long millis):等待当前线程最多执行millis毫秒,如果millis为0,则会一直执行;
    • 上述三种方法使线程等待后,可以通过Interrupt()显示唤醒(中断等待)
  • TERMINATED:run()方法完成时或者主线程main()方法完成时,线程就会关闭终止
    • 在一个终止的线程上调用 start() 方法,会抛出 java.lang.IllegalThreadStateException 异常

另外,我们可以通过创建线程的getState()方法获取当前线程状态,或者感兴趣的朋友可以去了解下Jstack怎么做线程状态分析,可以用来排查死锁或者一些CPU占用过高的问题

JVM线程与OS线程的状态关系

Java线程的状态只会因为自身程序执行而发生转变,一般内核不会改变JVM线程状态

JVM线程与OS线程不一定是对应的,需要通过映射完成:

  • NEW 创建状态,对应OS线程的创建状态 new

  • TERMINATED 销毁状态,对应OS线程的销毁状态 end

  • RUNNABLE 运行状态,对应OS线程的run运行状态ready就绪状态:只要操作系统正在运行,JVM就判定线程为run,并不一定对应内核线程的run状态。

    • 有时,OS线程阻塞,单JVM看来OS仍在运行。比如Scanner.in与Scoket.accpet等待输入时,JVM线程还是run状态,而其映射的内核线程状态是wait
  • WAITING 等待状态,对应OS线程的wait状态:一般是由于调用了wait一类的方法陷入等待。

    • wait的作用-线程协作机制:

      线程间并不都是竞争关系,也有协作关系。比如,一般一个进程中的多个线程除了普通线程外,还包括消耗线程、增加线程。消耗线程与增加线程间就是协作关系(生产者与消费者),所以需要wait,然后用notify特定唤醒,如果不特定唤醒,则会陷入线程的忙等待(比如说消耗线程没数据消费了,但是生产线程一直竞争不到执行权,没法生产新数据,消耗线程就一直等着)

      注意一下,wait通过notify唤醒后并不会立即执行,而是跟其他线程一起重新竞争锁 资源
      请添加图片描述

  • TIMED_WAITING 定时等待,对应OS线程的:相当于有限时间的wait,通过sleep等方式转变,通过interrupt打断。

    • sleep时会有锁的释放吗?

      不会,sleep本身与并发关系不大,不会进行锁操作,此时如果有synchronized同步块,其他线程仍然不能访问共享数据。

  • BLOCKED 无法获取锁时的阻塞,就对应OS的block状态

    • WAITINGBLOCKED 的区别,一个是主动,一个是被动

Reference

https://www.runoob.com/java/thread-status.html
http://concurrent.redspider.group/article/01/4.html
https://www.bilibili.com/video/BV172421P7MB/?share_source=copy_web&vd_source=e40b707ba9b46ace5a15c44fb5fa3388
https://juejin.cn/post/7016228406220029983
https://www.zhihu.com/question/64100112/answer/218379442

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/297919.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用虚拟引擎为AR体验提供动力

Powering AR Experiences with Unreal Engine ​​​​​​​ 目录 1. 虚拟引擎概述 2. 虚拟引擎如何为AR体验提供动力 3. 虚拟引擎中AR体验的组成部分是什么? 4. 使用虚拟引擎创建AR体验 5. 虚拟引擎中AR的优化提示 6. 将互动性融入AR与虚拟引擎 7. 在AR中…

简述JMeter实现分布式并发及操作

为什么要分布式并发? JMeter性能实践过程中,一旦进行高并发操作时就会出现以下尴尬场景,JMeter客户端卡死、请求错误或是超时等,导致很难得出准确的性能测试结论。 目前知道的有两个方法可以解决JMeter支撑高并发: …

【Android Studio】上位机-安卓系统手机-蓝牙调试助手

【Android Studio】上位机-安卓系统手机-蓝牙调试助手 文章目录 前言AS官网一、手机配置二、移植工程三、配置四、BUG五、Java语言总结 前言 提示:以下是本篇文章正文内容,下面案例可供参考 AS官网 AS官网 一、手机配置 Android Studio 下真机调试 …

Rust egui(4) 增加自己的tab页面

如下图,增加一个Sins也面,里面添加一个配置组为Sin Paraemters,里面包含一个nums的参数,范围是1-1024,根据nums的数量,在Panel中画sin函数的line。 demo见:https://crazyskady.github.io/index.…

Spring Boot 介绍

1、SpringBoot 介绍 用通俗的话讲,SpringBoot 在Spring生态基础上发展而来,它的发现不是取代Spring,是为了让人们更容易使用Spring。 2、相关依赖关系 Spring IOC/AOP > Spring > Spring Boot > Spring Cloud 3、 SpringBoot工作原…

ENSP中AC登录web界面

拓扑 虚拟网卡配置 云团配置: **AC配置** vlan batch 100 # interface GigabitEthernet0/0/1port link-type accessport default vlan 100 # interface Vlanif100ip address 192.168.0.1 255.255.255.0 #http server enable浏览器输入:http://192.168.…

前端 - 基础 表单标签 - 表单元素 input - type 属性 ( 单选按钮和复选按钮 )

input 标签 type 属性 ,上一篇讲了 输入框 和 密码框 这节看看 单选按钮 和 复选 按钮 目录 单选按钮 : 复选按钮 # 看上图就可以看到 单选按钮 -- radio 和 复选 按钮 -- checkbox 单选按钮 : 所谓单选按钮就是 有时…

某音乐平台歌曲信息逆向之参数寻找

如何逆向加密参数:某音乐平台歌曲信息逆向之webpack扣取-CSDN博客 参数构建 {"comm": {"cv": 4747474,"ct": 24,"format": "json","inCharset": "utf-8","outCharset": "ut…

HTML:框架

案例&#xff1a; <frameset cols"5%,*" ><frame src"left_frame.html"><frame src"right_frame.html"> </frameset> 一、<frameset>标签 <frameset>标签&#xff1a;称为框架标记&#xff0c;将一个HTML…

动态规划详解(Dynamic Programming)

目录 引入什么是动态规划&#xff1f;动态规划的特点解题办法解题套路框架举例说明斐波那契数列题目描述解题思路方式一&#xff1a;暴力求解思考 方式二&#xff1a;带备忘录的递归解法方式三&#xff1a;动态规划 推荐练手题目 引入 动态规划问题&#xff08;Dynamic Progra…

基于SpringBoot的“数码论坛系统设计与实现”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“数码论坛系统设计与实现”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体结构图 系统首页界面图 数码板…

一次java.lang.NullPointerException的排查之旅

一次java.lang.NullPointerException的排查之旅 问题由来问题分析问题处理 问题由来 最近在项目中遇到了一个比较奇怪的java.lang.NullPointerException&#xff0c;就是说在自己的本地环境中&#xff0c;功能正常&#xff0c;运行无异常。但是测试环境点击同样的功能时却总是…

【解读Kubernetes架构】全面指南,带你掌握Kubernetes的设计原理与构成!

了解 Kubernetes 架构&#xff1a;综合指南 前言一、什么是 Kubernetes 架构&#xff1f;1.1、控制平面1.2、工作节点 二、Kubernetes 控制平面组件2.1、kube-api服务器2.2、etcd2.3、kube-scheduler2.4、Kube 控制器管理器2.5、云控制器管理器 &#xff08;CCM&#xff09; 三…

CAD Plant3D 2023 下载地址及安装教程

CAD Plant3D是一款专业的三维工厂设计软件&#xff0c;用于在工业设备和管道设计领域进行建模和绘图。它是Autodesk公司旗下的AutoCAD系列产品之一&#xff0c;专门针对工艺、石油、化工、电力等行业的设计和工程项目。 CAD Plant3D提供了一套丰富的工具和功能&#xff0c;帮助…

matlab中角度-弧度转化

在 MATLAB 中进行角度和弧度之间的转换可以使用内置的函数&#xff1a; 1. 将角度转换为弧度&#xff1a; matlab rad deg * pi / 180; 这里 deg 是你想要转换的角度值&#xff0c;pi 是 MATLAB 内置的圆周率常量。 2. 将弧度转换为角度&#xff1a; matlab…

基于springboot+vue+Mysql的大学生租房系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

SambaNova 芯片:深入解析其架构和高性能秘诀

SambaNova——一家总部位于帕洛阿尔托的公司已经筹集了超过10亿美元的风险投资&#xff0c;不会直接向公司出售芯片。相反&#xff0c;它出售其定制技术堆栈的访问权限&#xff0c;该堆栈具有专门为运行最大的人工智能模型而设计的专有硬件和软件。 最近&#xff0c;SambaNova…

挖一挖:PostgreSQL Java里的double类型存储到varchar精度丢失问题

前言 大概故事是这样的&#xff0c;PostgreSQL数据库&#xff0c;表结构&#xff1a; create table t1(a varchar);然后使用标准的Java jdbc去插入数据&#xff0c;其基本代码如下&#xff1a; import java.sql.*; public class PgDoubleTest {public static void main(Stri…

【VSCode】修改插件地址

不想放在原始C盘下面C:\Users\{用户}\.vscode\extensions为了后续存储空间考虑&#xff0c;想通过添加环境变量创建名为VSCODE_EXTENSIONS的环境变量&#xff0c;内容指向vs Code扩展所在目录即可 直接配置环境变量&#xff0c;不要在有空格的文件夹下面 变量名称&#xff1a;…

Pygame基础10-物理模拟

PyMunk PyMunk是一个模拟物理的库。 注意&#xff0c;PyMunk只是进行物理模拟&#xff0c;不包含可视化的功能。如果需要可视化&#xff0c;可使用pygame等库。 可用pip安装pymunk pip install pymunk pymunk中的概念&#xff1a; space&#xff1a; 物理空间。 包含gravity 模…