【JUC并发编程系列】深入理解Java并发机制:从用户态到内核态的探索(一、前置知识)

文章目录

  • 【JUC并发编程系列】深入理解Java并发机制:从用户态到内核态的探索(一、前置知识)
    • 1.用户态与内核态区别
    • 2. 线程安全同步的方式
    • 3. 传统锁有哪些缺点
    • 4. 发生CPU上下文切换的原因
    • 5. 如何避免上下文切换
    • 6. 详细总结
      • 6.1 用户态与内核态
      • 6.2 线程安全同步方式
      • 6.3 传统锁的缺点
      • 6.4 CAS算法
      • 6.5 原子类(Atomic类)
      • 6.6 上下文切换

【JUC并发编程系列】深入理解Java并发机制:从用户态到内核态的探索(一、前置知识)

1.用户态与内核态区别

内核态(Kernel Mode):运行操作系统程序,操作硬件 (内核空间)

用户态(User Mode):运行用户程序(用户空间)

为了安全应用程序无法直接调用的硬件的功能,而是将这些功能封装成特定的函数。当应用程序需要硬件功能时(例如读写文件),就需要进行系统调用。当进程进行系统调用后就从用户态装换为内核态。

img

比如:线程的调度需要内核态调度实现

Linux使用了Ring3级别表示用户态,Ring0标识内核态

Ring0作为内核态,没有使用Ring1和Ring2。

Ring3状态不能访问Ring0的地址 空间,包括代码和数据。、

2. 线程安全同步的方式

  • 阻塞式:synchronized/ lock(aqs) 当前线程如果没有获取到锁,当前的线程就会被阻塞等待。

  • 非阻塞式:CAS 当前线程如果没有获取到锁,不会阻塞等待 一直不断重试

T1线程获取到锁 持久时间 几毫秒 1毫秒 唤醒t2线程

T2线程没有获取到锁 直接阻塞等待

阻塞----就绪状态—cpu调度

唤醒t2线程

如果没有获取到锁,当前的线程就会被阻塞等待------重量级锁

CAS 运行用户态

3. 传统锁有哪些缺点

在使用synchronized1.0版本 如果没有获取到锁的情况下则当前线程直接会变为阻塞的

状态----升级为重量级锁,在后期唤醒的成本会非常高。

C A S ----运行用户态 缺点:cpu飙高

偏向锁 →轻量级锁(cas)→重量级锁。

轻量级都是在用户态完成;

重量级需要用户态与内核态切换;

因为:重量级锁需要通过操作系统自身的互斥量(mutex lock,也称为互斥锁)来实现,然而这种实现方式需要通过用户态和核心态的切换来实现,但这个切换的过程会带来很大的性能开销,比如:Linux内核互斥锁–mutex。

Linux内核互斥锁mutex lock:

  1. atomic_t count; //指示互斥锁的状态:

​ 1:没有上锁,可以获得;

​ 0:被锁定,不能获得。

​ 负数:被锁定,且可能在该锁上有等待进程 ,初始化为没有上锁。

  1. spinlock_t wait_lock; //等待获取互斥锁中使用的自旋锁。在获取互斥锁的过程中,操作会在自旋锁的保护中进行。初始化为为锁定。

  2. struct list_head wait_list; //等待互斥锁的进程队列。

Synchronized 获取锁的流程:需要经历 用户态与内核态切换

唤醒他:内核态阻塞—唤醒 切换用户态重新cpu调度。

申请锁时,从用户态进入内核态,申请到后从内核态返回用户态(两次切换);没有申请到时阻塞睡眠在内核态。使用完资源后释放锁,从用户态进入内核态,唤醒阻塞等待锁的进程,返回用户态(又两次切换);被唤醒进程在内核态申请到锁,返回用户态(可能其他申请锁的进程又要阻塞)。所以,使用一次锁,包括申请,持有到释放,当前进程要进行四次用户态与内核态的切换。同时,其他竞争锁的进程在这个过程中也要进行一次切换。

CPU通过分配时间片来执行任务,一个CPU在一个时刻只能运行一个线程,当一个任务的时间片用完(时间片耗尽或出现阻塞等情况),CPU会转去执行另外一个线程切换到另一个任务。在切换之前会保存上一个任务的状态(当前线程的任务可能并没有执行完毕,所以在进行切换时需要保存线程的运行状态),当下次再重新切换到该任务,就会继续切换之前的状态运行。——任务从保存到再加载的过程就是一次上下文切换

上下文切换只能发生在内核态中。内核态是 CPU 的一种有特权的模式,在这种模式下只有内核运行并且可以访问所有内存和其他系统资源。其他的程序,如应用程序,在最开始都是运行在用户态,但是他们能通过系统调用来运行部分内核的代码

而CAS 是在用户态完成而CAS基于硬件实现,不需要进入内核,不需要切换线程,操作自旋几率较少 。

4. 发生CPU上下文切换的原因

  1. 通过调用下列方法会导致自发性上下文切换:

    • Thread.sleep()
    • Object.wait()
    • Thread.yeild()
    • Thread.join()
    • LockSupport.park()
  2. 发生下列情况可能导致非自发性上下文切换:

    • 切出线程的时间片用完
    • 有一个比切出线程优先级更高的线程需要被运行
    • 虚拟机的垃圾回收动作

5. 如何避免上下文切换

  1. 无锁并发编程。多线程竞争锁时,多线程竞争锁时,加锁、释放锁会导致比较多的上下文切换;
  2. CAS算法,Java的Atomic包使用CAS算法来更新数据,而不需要加锁,可能会消耗cpu资源。
  3. 使用最少线程,避免创建不需要的线程;
  4. 协程:在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换。

6. 详细总结

6.1 用户态与内核态

  • 内核态(Kernel Mode): 内核态是指操作系统运行的环境,具有最高权限,可以直接访问硬件资源,执行关键操作,如管理内存、处理器和外设等。在内核态下,操作系统可以执行任何指令。
  • 用户态(User Mode): 用户态是指应用程序运行的环境,权限较低,不能直接访问硬件资源。应用程序必须通过系统调用请求内核来执行特定操作,如文件读写、网络通信等。

当应用程序需要执行特定的硬件操作时,如读写文件或访问设备,它需要从用户态发起系统调用进入内核态。系统调用完成后,程序会回到用户态继续执行。

6.2 线程安全同步方式

  • 阻塞式同步: 使用synchronized关键字或基于AQS的锁机制实现。当一个线程试图获取一个已经被占用的锁时,该线程会被阻塞,直到锁被释放。
  • 非阻塞式同步: 使用CAS(Compare and Swap)算法实现。当线程尝试获取锁时,如果锁不可用,则线程不会被阻塞,而是继续重试直到成功。

6.3 传统锁的缺点

  • 重量级锁: 在早期的JVM实现中,如synchronized 1.0版本,如果线程无法获取锁,会直接进入阻塞状态,这会导致线程状态的转换成本较高,尤其是在锁释放后的唤醒成本。
  • 上下文切换: 重量级锁涉及从用户态到内核态的转换,这会触发上下文切换,进而影响性能。

6.4 CAS算法

  • CAS算法: CAS是一种非阻塞算法,用于实现原子操作。它由三个操作数组成:内存值(V)、旧的预期值(E)和要修改的新值(N)。当且仅当预期值E等于内存值V时,才会将内存值V更新为N。
  • 优点: CAS算法运行在用户态,不需要进入内核态,减少了上下文切换的开销。
  • 缺点: 在某些情况下可能会导致CPU空转,从而消耗大量CPU资源。

6.5 原子类(Atomic类)

  • 原子类: Java并发包提供了一系列原子类,它们利用CAS算法实现线程安全的数据更新。
    • 基本类型原子类: 如AtomicIntegerAtomicLong等。
    • 数组原子类: 如AtomicIntegerArrayAtomicLongArray等。
    • 引用类型原子类: 如AtomicReferenceAtomicStampedReference等。
    • 字段更新器: 如AtomicIntegerFieldUpdaterAtomicLongFieldUpdater等。
  • 底层实现: 原子类通常基于Unsafe类实现,通过反射获取Unsafe实例,并使用它的方法来实现CAS操作。

6.6 上下文切换

  • 发生原因: 上下文切换通常发生在线程的时间片结束、更高优先级的线程到达或者线程主动让出CPU时。
  • 避免方法:
    • 使用无锁编程技术。
    • 使用CAS算法减少锁的使用。
    • 减少线程数量,避免不必要的线程创建。
    • 使用协程技术来实现更高效的并发控制。

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

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

相关文章

Python3.11二进制AI项目程序打包为苹果Mac App(DMG)-应用程序pyinstaller制作流程(AppleSilicon)

众所周知,苹果MacOs系统虽然贵为Unix内核系统,但由于系统不支持N卡,所以如果想在本地跑AI项目,还需要对相关的AI模块进行定制化操作,本次我们演示一下如何将基于Python3.11的AI项目程序打包为MacOS可以直接运行的DMG安…

Python(R)均方根误差平均绝对误差导图

🎯要点 回归模型评估指标评估薪水预测模型评估员工倦怠率模型评估大气分析生成式对抗模型目标对象缺失下,性能估算法追踪模型误差指标降尺度大气学模拟模型准确性评估蛋白染色质相互作用模型评估 Python回归误差指标 平均绝对误差表示数据集中实际值和…

【flask框架搭建服务器demo】Python 使用轻量级 Flask 框架搭建 Web 服务器可视化数据库数据demo

本文适合刚入门flask框架用来熟悉项目的开发人员,关于flask框架的组成概念一些用法请参考下面的文章 https://blog.csdn.net/qq_47452807/article/details/122289200 本文主要给出一个可视化sqlite数据库数据的demo,先展示一下效果: 主要的…

【uniapp/uview1.x】u-collapse 高度随内容自适应

当 u-collapse-items 中的内容为动态的时候&#xff0c;会发生这种情况&#xff1a; 在 uview 官网中有一个方法可以解决&#xff1a; 具体方法&#xff1a; 在 u-collapse 标签中配置 ref"collapse"&#xff1a; <u-collapse ref"collapse" :item-…

Golang | Leetcode Golang题解之第376摆动序列

题目&#xff1a; 题解&#xff1a; int wiggleMaxLength(int* nums, int numsSize) {if (numsSize < 2) {return numsSize;}int prevdiff nums[1] - nums[0];int ret prevdiff ! 0 ? 2 : 1;for (int i 2; i < numsSize; i) {int diff nums[i] - nums[i - 1];if ((…

使用notepad++将shell脚本转为UNIX格式方法(主要差别在换行符)

sh文件尽量在linux上改&#xff0c;因windows和linux换行符不同&#xff0c;在windows上改后&#xff0c;在linux上改可能会出现换行符错误。 windows换行符 linux换行符 windows环境改换行符方法 使用notepad点 编辑–》文档格式转换–》转换未unix格式。 注&#xff1a;tx…

C# 泛型类型的约束详解与示例

文章目录 一、泛型约束概述二、泛型约束详解与示例1. 类约束2. 接口约束3. 引用类型约束4. 值类型约束5. 无参数构造函数约束6、多重约束7、默认构造函数约束8、基类和接口的组合约束 三、总结 在C#编程语言中&#xff0c;泛型是一种非常强大的特性&#xff0c;它允许我们编写可…

鸿蒙卡片服务开发

首先先创建一个项目 在该项目下创建一个卡片服务 在module.json5文件下配置 {"module": {..."extensionAbilities": [{"name": "EntryFormAbility","srcEntry": "./ets/entryformability/EntryFormAbility.ets",…

Apache Tomcat与反向代理

Apache Tomcat 是一个开源的 Java Servlet 容器&#xff0c;主要用于部署和运行基于 Java 的 Web 应用程序。Tomcat 提供了一个环境&#xff0c;让开发者能够使用 Java 编写的 Web 应用程序在 Web 服务器上运行。下面是对 Tomcat 的详细介绍&#xff1a; Tomcat 的历史 Tomca…

Unity 中使用SQLite数据库

文章目录 0.参考文章1.Presentation —— 介绍2.&#xff08;SQLite4Unity3d&#xff09;Unity中直接使用SQLite的插件3.创建数据库4.创建表5.Navicat Premium&#xff08;数据库可视化&#xff09;6.增删改查6.1 增6.2 删6.3 改6.4 查 0.参考文章 https://blog.csdn.net/Chin…

干货 | 关于Armv7m异常进入的经验分享

一、 概述 这里主要介绍异常的进入行为&#xff08;不包括复位异常&#xff09;。&#xff08;这里主要参考 armv7m&#xff09;。 二、异常进入 在发生抢占的时候&#xff08;异常发生且开始执行&#xff09;&#xff0c;硬件将上下文状态保存到一个 SP 寄存器指向的栈中&a…

优化|贝叶斯优化系列(二):大规模贝叶斯优化算法

原文&#xff1a;When Gaussian Process Meets Big Data: A Reviewof Scalable GPs 原文作者&#xff1a;Haitao Liu , Yew-Soon Ong 论文解读者&#xff1a;赵进 编者按 高斯过程模型因其出色的预测性能在仿真建模中得到了广泛应用&#xff0c;然而在当今大数据时代&#xf…

百度翻译与TOP3在线翻译伙伴:2024年的黄金组合

在这个信息丰富的时代&#xff0c;语言帮助人们跨越地域界限进行交流。随着全球化的发展&#xff0c;高效的在线翻译工具变得越来越重要&#xff0c;它能帮我们更好地了解世界和不同的文化。今天&#xff0c;我们就来看看百度翻译和它的三个新对手之间的比较&#xff0c;一起找…

Codeforces Round 916 (Div. 3) E1. Game with Marbles(博弈论*1400)

感觉很难想。 如果你直接想的话&#xff0c;你就会发现有很多做法可以选择&#xff0c;而你根本不知道应该选哪个。 这时候可以先假设鲍勃已经取走了爱丽丝的所有的颜色的弹珠&#xff0c;&#xff08;并且以每个颜色一个弹珠的代价&#xff09;。 这时候每一项得分就是 S i …

Dubbo 内置容器:Spring Container

Dubbo 内置容器&#xff1a;Spring Container 1、核心点2、误解澄清 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; Dubbo本身并不直接提供容器服务&#xff0c;而是深度集成了Spring框架&#xff0c;实现了对Spring Container的全面支持。…

游戏开发设计模式之原型模式

目录 原型模式的实现步骤 原型模式的优点 原型模式的应用场景 总结 原型模式在游戏开发中的具体应用案例是什么&#xff1f; 如何在不同编程语言中实现原型模式&#xff1f; Java C# Python C JavaScript 原型模式与其他创建型设计模式&#xff08;如建造者模式、适…

Modern restaurant - building and interior (餐厅场景)

餐厅是模块化的,因此您可以使用提供的构造元素(如墙壁模块、地板模块、窗户、吧台、厨房模块、门、天花板模块等)进一步设计自己的餐厅。 图像和视频中显示的完整场景包含在此资源包中,可以用作游戏和3D项目的起点! ★ 主要特点 ★ 全模块化内饰和外观 全模块化厨房和餐厅…

PTA统计一行文本的单词个数

本题目要求编写程序统计一行字符中单词的个数。所谓“单词”是指连续不含空格的字符串&#xff0c;各单词之间用空格分隔&#xff0c;空格数可以是多个。 输入格式: 输入给出一行字符。 输出格式: 在一行中输出单词个数。 输入样例: Lets go to room 209.输出样例: 5解题…

【惠农网-注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

Backtrader 实现和理解海龟交易法

Backtrader 实现和理解海龟交易法 1. 海龟交易的理解 &#xff08;1&#xff09;资金管理 海龟将总资金分为N个交易单位&#xff0c;每个单位即称为头寸&#xff0c;划分的标准主要是参考标的的波动性。 波动性用一个指标量化即真实波动幅度均值&#xff08;ATR&#xff09;…