【java并发编程】底层原理——用户态和内核态的区别

【java并发编程】底层原理——用户态和内核态的区别一、背景–线程状态切换的代价java的线程是映射到操作系统原生线程之上的,如果要阻塞或唤醒一个线程就需要操作系统介入,需要在户态与核心态之间切换,这种切换会消耗大量的系统资源,因为用户态与内核态都有各自专用的内存空间,专用的寄存器等,用户态切换至内核态需要传递给许多变量、参数给内核,内核也需要保护好用户态在切换时的一些寄存器值、变量等,以便内核态调用结束后切换回用户态继续工作。synch…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

一、背景–线程状态切换的代价

java的线程是映射到操作系统原生线程之上的,如果要阻塞或唤醒一个线程就需要操作系统介入,需要在户态与核心态之间切换,这种切换会消耗大量的系统资源,因为用户态与内核态都有各自专用的内存空间,专用的寄存器等,用户态切换至内核态需要传递给许多变量、参数给内核,内核也需要保护好用户态在切换时的一些寄存器值、变量等,以便内核态调用结束后切换回用户态继续工作。

synchronized会导致争用不到锁的线程进入阻塞状态,所以说它是java语言中一个重量级的同步操纵,被称为重量级锁,为了缓解上述性能问题,JVM从1.5开始,引入了轻量锁与偏向锁,默认启用了自旋锁,他们都属于乐观锁。所以明确java线程切换的代价,是理解java中各种锁的优缺点的基础之一。

 

二、用户态和内核态的概念

2.1内核态

CPU可以访问内存所有数据, 包括外围设备, 例如硬盘, 网卡. CPU也可以将自己从一个程序切换到另一个程序

2.2用户态

只能受限的访问内存, 且不允许访问外围设备. 占用CPU的能力被剥夺, CPU资源可以被其他程序获取

由于需要限制不同的程序之间的访问能力, 防止他们获取别的程序的内存数据, 或者获取外围设备的数据, 并发送到网络, CPU划分出两个权限等级 :用户态内核态 

 

 

三、用户态与内核态的切换

所有用户程序都是运行在用户态的, 但是有时候程序确实需要做一些内核态的事情, 例如从硬盘读取数据, 或者从键盘获取输入等.,而唯一可以做这些事情的就是操作系统, 所以此时程序就需要先操作系统请求以程序的名义来执行这些操作(比如java的I/O操作底层都是通过native方法来调用操作系统)。

这时需要一个这样的机制: 用户态程序切换到内核态, 但是不能控制在内核态中执行的指令。

这种机制叫系统调用, 在CPU中的实现称之为陷阱指令(Trap Instruction)

他们的工作流程如下:

  1. 用户态程序将一些数据值放在寄存器中, 或者使用参数创建一个堆栈(stack frame), 以此表明需要操作系统提供的服务.
  2. 用户态程序执行陷阱指令
  3. CPU切换到内核态, 并跳到位于内存指定位置的指令, 这些指令是操作系统的一部分, 他们具有内存保护, 不可被用户态程序访问
  4. 这些指令称之为陷阱(trap)或者系统调用处理器(system call handler). 他们会读取程序放入内存的数据参数, 并执行程序请求的服务
  5. 系统调用完成后, 操作系统会重置CPU为用户态并返回系统调用的结果

当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核 代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。当进程在执行用户自己的代码时,则称其处于用户运行 态(用户态)。即此时处理器在特权级最低的(3级)用户代码中运行。当正在执行用户程序而突然被中断程序中断时,此时用户程序也可以象征性地称为处于进程 的内核态。因为中断处理程序将使用当前进程的内核栈。这与处于内核态的进程的状态有些类似。

我们在系统中执行一个程序时,大部分时间是运行在用户态下的,在其需要操作系 统帮助完成某些它没有权力和能力完成的工作时就会切换到内核态,比如前面提到的Java程序阻塞和唤醒一个线程时就需要切换到内核态。

补充:内核态与用户态在操作系统中的详细执行过程

内核态与用户态是操作系统的两种运行级别, 跟intel cpu没有必然的联系, intel cpu提供Ring0-Ring3三种级别的运行模式,Ring0级别最高,Ring3最低。Linux使用了Ring3级别运行用户态,Ring0作为 内核态,没有使用Ring1和Ring2。Ring3状态不能访问Ring0的地址空间,包括代码和数据。Linux进程的4GB地址空间,3G-4G部 分大家是共享的,是内核态的地址空间,这里存放在整个内核的代码和所有的内核模块,以及内核所维护的数据。用户运行一个程序,该程序所创建的进程开始是运 行在用户态的,如果要执行文件操作,网络数据发送等操作,必须通过write,send等系统调用,这些系统调用会调用内核中的代码来完成操作,这时,必 须切换到Ring0,然后进入3GB-4GB中的内核地址空间去执行这些代码完成操作,完成后,切换回Ring3,回到用户态。这样,用户态的程序就不能 随意操作内核地址空间,具有一定的安全保护作用。
至于说保护模式,是说通过内存页表操作等机制,保证进程间的地址空间不会互相冲突,一个进程的操作不会修改另一个进程的地址空间中的数据。

 

四、用户态切换到内核态的3种方式

4.1 系统调用

这是用户态进程主动要求切换到内核态的一种方式,用户态进程通过系统调用申请使 用操作系统提供的服务程序完成工作,比如print()实际上就是执行了一个输出的系统调用。而系统调用的机制其核心还是使用了操作系统为用户 特别开放的一个中断来实现,例如Linux的int 80h中断。

4.2 异常

当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。

4.3 外围设备的中断

当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会 暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到 内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。

 

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/192143.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 如何给mysql创建一个账户「建议收藏」

    如何给mysql创建一个账户「建议收藏」1.使用root账户登录到mysql:mysql -uroot -p2.创建用户名和密码:grant all on *.* to 用户名@’127.0.0.1′ identified by "密码";3.创建成功后,需设置访问权限。首先切换到mysql数据库:use mysql;4.修改新建用户的权限:update user set host = ‘%’ where user = ‘attckne…

    2022年8月18日
    11
  • linux配置环境变量jdk_java配置环境变量详解

    linux配置环境变量jdk_java配置环境变量详解在配置Linux系统服务器的时候,我们常常需要设置系统环境变量,这篇文章就是总结几种常见的配置环境变量的方式。

    2025年8月23日
    2
  • Ubuntu下安装lrzsz「建议收藏」

    Ubuntu下安装lrzsz「建议收藏」Ubuntu安装lrzsz使用阿里云时想要上传文件到服务器,使用Xshell远程上传文件,提示安装lrzsz,所以了解一下lrzsz的安装过程在此记录一下。1、下载lrzsz压缩包#wgethttps://ohse.de/uwe/releases/lrzsz-0.12.20.tar.gz2、解压#tarzxvflrzsz-0.12.20.tar.gz   …

    2022年6月23日
    163
  • markdown文本居中_markdown居中语法

    markdown文本居中_markdown居中语法示例表格序号偏移说明10表格说明22表格说明34表格说明实现的代码是下面这样的。<!–让表格居中显示的风格–><style>.center{width:auto;display:table;margin-left:auto;margin-right:auto;}</style><palign=”center”><fontfac..

    2022年9月19日
    2
  • Maven菜鸟教程:Maven仓库的分类[通俗易懂]

    Maven菜鸟教程:Maven仓库的分类[通俗易懂]Maven菜鸟教程中有很多知识点需要大家学习,Maven仓库分类就是其中一点,为了更具体地增加对仓库的理解,这里详细介绍一下各种仓库。本地仓库Maven在根据坐标查找依赖的构件时,先是在本地仓库中查找。默认情况下,不管是Windows操作系统还是Linux操作系统,每个用户在自己的用户目录下都有一个路径名为.m2/repository/的目录,这个目录就是Maven的本地仓库目录。比如,笔者的用户名是Noble,计算机上的默认本地仓库的目录就是C:\Users\Noble.m2

    2025年10月8日
    2
  • 移动端开发遇到的一些兼容性问题及其整理「建议收藏」

    移动端开发遇到的一些兼容性问题及其整理「建议收藏」IOS手机测试时会发现加了margin-bottom的属性无效。解决:替换为padding-bottom或者放个空盒子有高度宽度占位即可。IOS手机的输入框出现未知的内阴影。解决:input:{-webkit-appearance:none;}控制手机上方的标题:document.title;…

    2022年6月24日
    39

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号