当前位置: 首页 > news >正文

操作系统导论——第26章 并发:介绍

        本章介绍为单个运行进程提供的新抽象:线程(thread)。经典观点是一个程序只有一个执行点(一个程序计数器,用来存放要执行的指令),但多线程(multi-threaded)程序会有多个执行点(多个程序计数器,每个都用于取指令和执行)。换一个角度来看,每个线程类似于独立的进程,只有一点区别:它们共享地址空间,从而能够访问相同的数据

        因此,单个线程的状态与进程状态非常类似。线程有一个程序计数器(PC),记录程序从哪里获取指令。每个线程有自己的一组用于计算的寄存器。所以,如果有两个线程运行在一个处理器上,从运行一个线程(T1)切换到另一个线程(T2)时,必定发生上下文切换(context switch)。线程之间的上下文切换类似于进程间的上下文切换。对于进程,我们将状态保存到进程控制块(Process Control Block,PCB)。现在,我们需要一个或多个线程控制块(Thread Control Block,TCB,保存每个线程的状态。但是,与进程相比,线程之间的上下文切换有一点主要区别:地址空间保持不变(即不需要切换当前使用的页表)

        线程和进程之间的另一个主要区别在于。在简单的传统进程地址空间模型 [ 可以称之为单线程(single-threaded)进程] 中,只有一个栈,通常位于地址空间的底部(见 图26.1 左图)。 

        然而,在多线程的进程中,每个线程独立运行,可以调用各种例程来完成正在执行的任何工作。不是地址空间中只有一个栈,而是每个线程都有一个栈。 假设有一个多线程的进程,它有两个线程,结果地址空间看起来不同。(图26.1 右图)

 

         在 图26.1 中,可以看到两个栈跨越了进程的地址空间。因此,所有位于栈上的变量、参数返回值和其他放在栈上的东西,将被放置在有时称为线程本地(thread-local)存储的地方,即相关线程的栈。

一、实例:线程创建

         假设想运行一个程序,它创建两个线程,每个线程都做了一些独立的工作,在这例子中,打印“A”或“B”。代码如图26.2所示。

        主程序创建了两个线程,分别执行函数 mythread(),但是传入不同的参数(字符串类型的 A或者 B)。一旦线程创建,可能会立即运行(取决于调度程序的兴致),或者处于就绪状态,等待执行。创建了两个线程(T1和T2)后,主程序调用pthread_join(),等待特定线程完成。 

 

        小程序可能执行顺序,在表 26.1 中,向下方向表示时间增加,每个列显式不同的线程(主线程、线程1 或 线程2)何时运行。 

 

        但请注意,这种排序不是唯一可能的顺序。实际上,给定一系列指令,有很多可能的顺序,这取决于调度程序决定在给定时刻运行哪个线程。例如,创建一个线程后,它可能会立即运行,这将导致表26.2中的执行顺序。

        我们甚至可以在 “A” 之前看到 “B”,即使先前创建了线程1,如果调度程序决定先运行线程2,没有理由认为先创建的线程先运行。表26.3展示了最终的执行顺序,线程2在线程1之前先展示结果

 

二、为什么更糟糕:共享数据

        上面演示的简单线程示例非常有用,它展示了线程如何创建,根据调度程序的决定,它们如何以不同顺序运行。但是,它没有展示线程在访问共享数据时如何相互作用

      设想一个简单的例子,其中两个线程希望更新全局共享变量。我们要研究的代码如图26.3 所示

#include <stdio.h> 
#include <pthread.h> 
#include "mythreads.h" static volatile int counter = 0; // 
// mythread() 
//    // Simply adds 1 to counter repeatedly, in a loop 
// No, this is not how you would add 10,000,000 to 
// a counter, but it shows the problem nicely. 
// 
void * 
mythread(void *arg) 
{ printf("%s: begin\n", (char *) arg); int i; for (i = 0; i < 1e7; i++) { counter = counter + 1; } printf("%s: done\n", (char *) arg); return NULL; 
}  
// 
// main() 
//  
// Just launches two threads (pthread_create)    
// and then waits for them (pthread_join) 
int 
main(int argc, char *argv[]) 
{ pthread_t p1, p2; printf("main: begin (counter = %d)\n", counter); Pthread_create(&p1, NULL, mythread, "A"); Pthread_create(&p2, NULL, mythread, "B"); // join waits for the threads to finish Pthread_join(p1, NULL); Pthread_join(p2, NULL); printf("main: done with both (counter = %d)\n", counter); return 0; 
} 

        以下是代码的一些说明:封装了线程创建和合并例程以便在失败时退出。对于这样简单的程序,我们希望至少注意到发生了错误(如果发生了错误),但不做任何非常聪明的处理(只是退出)。因此,Pthread_create()只需调用 pthread_create(),并确保返回码为 0。如果不是,Pthread_create()就打印一条消息并退出

        其次,没有用两个独立的函数作为工作线程,只使用了一段代码,并向线程传入一个参数(本例中是一个字符串),这样就可以让每个线程在打印其消息前,打印不同的字母。 

        最后,可以看每个工作线程正在尝试做什么:向共享变量计数器添加一个数字,并在循环中执行 1000万次。因此,预期结果是:20000000。

        现在编译并运行该程序,观察它的行为。有时候,一切如我们预期的那样:

三、核心问题:不可控的调度

        为了理解为什么会发生这种情况,我们必须了解编译器为更新计数器生成的代码序列。 在这个例子中,只是给 counter 加上一个数字(1)。因此,做这件事的代码序列可能看起来像这样(在x86中):

mov 0x8049a1c,%eax

add $0x1,%eax

mov %eax,0x8049a1c

        这个例子假定,变量 counter 位于地址 0x8049a1c。在这3条指令中,先用x86的 mov 指令,从内存地址处取出值,放入 eax。然后,给 eax 寄存器的值加 1(0x1)。最后,eax 的值被存回内存中相同的地址。

         设想两个线程之一(线程1)进入这个代码区域,并且因此将要增加一个计数器。它将counter 的值(假设它这时是50)加载到它的寄存器 eax 中。因此,线程1 的 eax = 50。然后它向寄存器加 1,因此 eax = 51。现在,①一件不幸的事情发生了:时钟中断发生。因此,操作系统将当前正在运行的线程(它的程序计数器、寄存器,包括eax等)的状态保存到线程的TCB

        现在更糟的事发生了:线程 2 被选中运行,并进入同一段代码。它也执行了第一条指令,获取计数器的值并将其放入其 eax 中 [请记住:运行时每个线程都有自己的专用寄存器。上下文切换代码将寄存器虚拟化(virtualized),保存并恢复它们的值]。此时counter的值仍为 50,因此线程2的eax = 50。假设线程2执行接下来的两条指令,将eax递增1(因此eax = 51),然后将 eax 的内容保存到counter(地址0x8049a1c)中。因此,全局变量 counter现在的值是51

         ③ 最后,又发生一次上下文切换,线程 1 恢复运行。还记得它已经执行过 mov 和 add 指令,现在准备执行最后一条 mov 指令。回忆一下,eax=51。因此,最后的 mov 指令执行, 将值保存到内存,counter 再次被设置为51

简单来说,发生的情况是:增加 counter 的代码被执行两次,初始值为 50,但是结果为 51。这个程序的“ 正确 ”版本应该导致变量 counter 等于52。 

         为了更好地理解问题,追踪详细的执行。假设在这个例子中,上面的代码被加载到内存中的地址 100 上,就像下面的序列一样(熟悉类似 RISC 指令集的人请注意:x86 具有可变长度指令。这个 mov 指令占用 5 个字节的内存,add只占用3个字节):

100 mov 0x8049a1c, %eax

105 add  $0x1, %eax

108 mov %eax, 0x8049a1c

        发生的情况如表 26.4 所示。假设 counter 从 50 开始,并追踪这个例子,确保明白发生什么

        展示的情况称为竞态条件(race condition):结果取决于代码的时间执行。由于运气不好(即在执行过程中发生的上下文切换),得到了错误的结果。事实上,可能每次都会得到不同的结果。因此,我们称这个结果是不确定的(indeterminate),而不是确定的 (deterministic)计算(我们习惯于从计算机中得到)。不确定的计算不知道输出是什么,它在不同运行中确实可能是不同的。

        由于执行这段代码的多个线程可能导致竞争状态,因此我们将此段代码称为临界区 (critical section)。临界区是访问共享变量(或更一般地说,共享资源)的代码片段一定不能由多个线程同时执行。 

        真正想要的代码就是所谓的互斥(mutual exclusion)。这个属性保证了如果一个线程在临界区内执行,其他线程将被阻止进入临界区。 

四、原子性愿望

        解决这个问题的一种途径是拥有更强大的指令,单步就能完成要做的事,从而消除不合时宜的中断的可能性。比如,如果有这样一条超级指令怎么样?

memory-add 0x8049a1c , $0x1 

         假设这条指令将一个值添加到内存位置,并且硬件保证它以原子方式(atomically)执行。当指令执行时,它会像期望那样执行更新。它不能在指令中间中断,因为这正是我们从硬件获得的保证:发生中断时,指令根本没有运行,或者运行完成,没有中间状态

        在这里,原子方式的意思是“作为一个单元”,有时我们说“全部或没有”。希望以原子方式执行3个指令的序列:

 mov 0x8049a1c, %eax

add $0x1, %eax

mov %eax, 0x8049a1c

         如果有一条指令来做到这一点,我们可以发出这条指令然后完事。但在一般情况下,不会有这样的指令。设想我们要构建一个并发的 B 树,并希望更新它。我们真的希望硬件支持 “ B树的原子性更新 ” 指令吗?可能不会,至少理智的指令集不会。

        因此,要做的是要求硬件提供一些有用的指令,可以在这些指令上构建一个通用的集合,即所谓的同步原语(synchronization primitive)。通过使用这些硬件同步原语,加上操作系统的一些帮助,我们将能够构建多线程代码,以同步和受控的方式访问临界区,从而可靠地产生正确的结果—— 尽管有并发执行的挑战。

 

 五、等待另一个线程

        本章提出了并发问题,就好像线程之间只有一种交互,即访问共享变量,因此需要为临界区支持原子性。事实证明,还有另一种常见的交互,即一个线程在继续之前必须等待另一个线程完成某些操作。例如,当进程执行磁盘 I/O 并进入睡眠状态时,会产生这种交互。 当 I/O 完成时,该进程需要从睡眠中唤醒,以便继续进行。

        在接下来的章节中,我们不仅要研究如何构建对同步原语的支持来支持原子性, 还要研究支持在多线程程序中常见的睡眠/唤醒交互的机制

 

 

相关文章:

操作系统导论——第26章 并发:介绍

本章介绍为单个运行进程提供的新抽象&#xff1a;线程&#xff08;thread&#xff09;。经典观点是一个程序只有一个执行点&#xff08;一个程序计数器&#xff0c;用来存放要执行的指令&#xff09;&#xff0c;但多线程&#xff08;multi-threaded&#xff09;程序会有多个执…...

如何使用测试软件 Jmeter

第一步&#xff0c;点击 编辑 添加线程组 第二步&#xff0c;右键单击线程组&#xff0c;添加取样器 HTTP 请求 第三步&#xff0c;设置请求路径 第四步&#xff0c;添加 查看结果树 用于查看请求响应 最后点击绿色小三角启动即可...

HarmonyOS NEXT 免费无广告看电影app:从想法到实现的经验总结

学习一项新技能&#xff0c;最好也是最快的方法就是动手实战。学习鸿蒙也一样&#xff0c;给自己定一个小目标&#xff0c;直接找项目练,这样进步是最快的。最近&#xff0c;我在网上看到360周董的一句话&#xff1a;“想干什么就去干&#xff0c;干得烂总比不干强&#xff01;…...

《算法导论(第4版)》阅读笔记:p14-p16

《算法导论(第4版)》学习第 9 天&#xff0c;p14-p16 总结&#xff0c;总计 3 页。 一、技术总结 无。 二、英语总结(生词&#xff1a;2) 1. in light of (1)释义 idiom. in light of 是美式用法&#xff0c;英式用法是 in the light of。take sth into consideration(鉴…...

kuka, fanuc, abb机器人和移动相机的标定

基础知识 : 一, 9点标定之固定相机标定: 图1: 固定位置相机拍照 因为相机和机器人的基坐标系是固定的, 所以在海康威视相机的9点标定功能栏中, 填上海康使用“圆查找”捕捉到的坐标值, 再将机器人显示的工具坐标系在基坐标系的实时位置pos_act值填入物理坐标X, Y中即可 图2:…...

【MyBatis-6】MyBatis动态SQL:灵活构建高效数据库查询的艺术

在现代企业级应用开发中&#xff0c;与数据库的交互是不可或缺的核心部分。MyBatis作为一款优秀的持久层框架&#xff0c;因其简洁、灵活和高效而广受开发者喜爱。其中&#xff0c;动态SQL功能更是MyBatis的一大亮点&#xff0c;它允许开发者根据不同条件灵活构建SQL语句&#…...

从零开始理解FlashAttention:算法细节图解

&#x1f9e0; 向所有学习者致敬&#xff01; “学习不是装满一桶水&#xff0c;而是点燃一把火。” —— 叶芝 我的博客主页&#xff1a; https://lizheng.blog.csdn.net &#x1f310; 欢迎点击加入AI人工智能社区&#xff01; &#x1f680; 让我们一起努力&#xff0c;共创…...

js原型污染 + xss劫持base -- no-code b01lersctf 2025

题目信息:Found this new web framework the other day—you don’t need to write any code, just JSON. 我们先来搞清楚究竟发生了什么 当我们访问 /index /*** 处理 /:page 路径的 GET 请求* param {Object} req - 请求对象* param {Object} reply - 响应对象* returns {Pro…...

面试题:Java集合框架高频面试题总结

# Java集合框架高频面试题总结 ## 集合框架概述 1. **Java集合框架的主要组成部分** - Collection接口 - List: 有序可重复 - Set: 无序不可重复 - Queue: 队列 - Map接口: 键值对存储 2. **集合框架的继承体系** - Collection - List → Arra…...

【大模型ChatGPT+ArcGIS】数据处理、空间分析、可视化及多案例综合应用

在数字化和智能化的浪潮中&#xff0c;GIS&#xff08;地理信息系统&#xff09;和GPT&#xff08;生成式预训练模型&#xff09;的结合正日益成为推动科研、城市规划、环境监测等领域发展的关键技术。GIS以其强大的空间数据处理、先进的空间分析工具、灵活的地图制作与可视化能…...

使用JMETER中的JSON提取器实现接口关联

一、JSON提取器介绍 JSON提取器是JMETER工具中用于从JSON响应中提取数据的重要组件&#xff0c;常常用于接口关联场景中&#xff08;参数传递&#xff09;。 二、添加JSON提取器 举例&#xff08;积分支付接口请求数据依赖于创建订单接口响应的payOrderId&#xff09; 1.在…...

Filecoin存储管理:如何停止Lotus向特定存储路径写入新扇区数据

Filecoin存储管理&#xff1a;如何停止Lotus向特定存储路径写入新扇区数据 引言背景问题场景解决方案步骤1&#xff1a;修改sectorstore.json文件步骤2&#xff1a;重新加载存储配置步骤3&#xff1a;验证更改 技术原理替代方案最佳实践结论 引言 在Filecoin挖矿过程中&#x…...

Elasticsearch太重?它的超轻量的替代品找到了!

简要介绍 在海量数据时代&#xff0c;快速而精准地找到所需信息至关重要。如果您正为此苦恼&#xff0c;或者您是 Elasticsearch 的用户&#xff0c;并对其资源消耗或性能有所关注&#xff0c;那么今天我要向您介绍一款名为 Manticore Search 的开源搜索数据库&#xff0c;它或…...

【计算机视觉】OpenCV实战项目: Fire-Smoke-Dataset:基于OpenCV的早期火灾检测项目深度解析

Fire-Smoke-Dataset&#xff1a;基于OpenCV的早期火灾检测项目深度解析 在当今数字化时代&#xff0c;火灾检测技术的智能化发展至关重要。传统的火灾检测方法依赖于烟雾传感器或人工监控&#xff0c;往往存在响应延迟或误报的问题。而随着计算机视觉技术的飞速发展&#xff0…...

STM32--PWM--函数

TIM_OCInitTypeDef TIM_OCInitTypeDef 是 STM32 标准外设库中用于配置定时器输出比较&#xff08;Output Compare, OC&#xff09;功能的结构体&#xff0c;主要用于 PWM 生成、单脉冲输出等场景。 typedef struct {uint16_t TIM_OCMode; // 输出比较模式uint16_t TIM_…...

软件测试应用技术(3) -- 软件评测师(十六)

5 事件驱动架构软件测试 5.1 事件驱动架构软件测试概述 事件驱动架构&#xff0c;简称EDA&#xff0c;是常用的架构范式中的一种&#xff0c;其关注事件的产生、识别、处理、响应。对于事件驱动架构系统的测试应特别注意其业务逻辑处理上的异步特性导致的缺陷和事件队列处理中…...

人工智能之数学基础:二次型

本文重点 二次型作为线性代数领域的重要概念,架起了代数方程与几何分析之间的桥梁。从古典解析几何中的圆锥曲线方程到现代优化理论中的目标函数,二次型以其简洁的数学表达和丰富的结构特性,在数学物理、工程技术和经济金融等领域发挥着不可替代的作用。 二次型的基本概念…...

MongoDB 创建索引原则

MongoDB索引创建原则 MongoDB索引是提高查询性能的关键工具&#xff0c;以下是创建索引的核心原则和最佳实践&#xff1a; 一、索引基础原则 ‌1. 索引本质‌&#xff1a;索引类似书籍目录&#xff0c;通过B-Tree数据结构对字段值排序存储&#xff0c;使查询复杂度从O(n)降为…...

空间复杂度** 与 **所需辅助空间**

当我们说一个算法的 空间复杂度是 O(1)&#xff0c;通常特指“辅助空间”是 O(1)&#xff0c;即&#xff1a;除了输入数据本身之外&#xff0c;算法只使用常数级别的额外空间。 ✅ 正确认解&#xff1a; O(1) 空间复杂度 ≈ O(1) 辅助空间 这表示&#xff1a; 不随输入规模增长…...

Spring Web MVC快速入门

什么是Spring Web MVC Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架&#xff0c;从⼀开始就包含在 Spring 框架中。它的正式名称“Spring Web MVC”来⾃其源模块的名称(Spring-webmvc)&#xff0c;但它通常被称为"Spring MVC". View(视图) 指在应⽤程序…...

RT-Thread 深入系列 Part 1:RT-Thread 全景总览

摘要&#xff1a; 本文将从 RTOS 演进、RT-Thread 的版本分支、内核架构、核心特性、社区与生态、以及典型产品应用等多维度&#xff0c;全面呈现 RT-Thread 的全景图。 关键词&#xff1a;RT-Thread、RTOS、微内核、组件化、软件包管理、SMP 1. RTOS 演进与 RT-Thread 定位 2…...

黄金、碳排放期货市场API接口文档

StockTV 提供了多种期货市场的数据接口&#xff0c;包括获取K线图表数据、查询特定期货的实时行情等。以下为对接期货市场的详细接口说明。 一、获取K线图表数据 通过调用/futures/kline接口&#xff0c;您可以获取指定期货合约的历史K线数据&#xff08;例如开盘价、最高价、…...

SpringAI框架中的RAG知识库检索与增强生成模型详解

SpringAI框架中的RAG知识库检索与增强生成模型详解 一、RAG简介 RAG&#xff08;Retrieval-Augmented Generation&#xff09;可以通过检索知识库&#xff0c;克服大模型训练完成后参数冻结的局限性&#xff0c;携带知识让大模型根据知识进行回答。 二、SpringAI框架支持的R…...

LVGL- 按钮矩阵控件

1 按钮矩阵控件 lv_btnmatrix 是 LVGL&#xff08;Light and Versatile Graphics Library&#xff09; v8 中提供的一个非常实用的控件&#xff0c;用于创建带有多个按钮的矩阵布局。它常用于实现虚拟键盘、数字键盘、操作面板、选择菜单等场景&#xff0c;特别适用于嵌入式设…...

C++学习-入门到精通-【5】类模板array和vector、异常捕获

C学习-入门到精通-【5】类模板array和vector、异常捕获 类模板array和vector、异常捕获 C学习-入门到精通-【5】类模板array和vector、异常捕获一、array对象array对象的声明使用array对象的例子使用常量变量指定array对象的大小 二、基于范围的for语句三、利用array对象存放成…...

`待办事项css样式

vue <template> <div class"box"> <div class"head"> <h2>待办事项</h2> <input type"text" placeholder"请输入您的待办事项&#xff0c;按回车添加"> </div> <div class"main&q…...

spring ai alibaba 使用 SystemPromptTemplate 很方便的集成 系统提示词

系统提示词可以是.st 文件了&#xff0c;便于修改和维护 1提示词内容&#xff1a; 你是一个有用的AI助手。 你是一个帮助人们查找信息的人工智能助手。 您的名字是{name} 你应该用你的名字和{voice}的风格回复用户的请求。 每一次回答的时候都要增加一个65字以内的标题形如:【…...

Vue3 官方宣布淘汰 Axios,拥抱Alova.js

过去十年,Axios 凭借其简洁的API设计和浏览器/Node.js双环境支持,成为前端开发者的首选请求库。但随着现代前端框架的演进和工程化需求的升级,Alova.js 以更轻量、更智能、更符合现代开发范式的姿态登场。 一、Axios的痛点 1,冗余的适配逻辑,比如Axios的通用配置(但实际…...

2025年数维杯C题数据收集方式分享

2025年数维杯C题”清明时节雨纷纷&#xff0c;何处踏青不误春&#xff1f;“需要我们根据题目的要求自行数据&#xff0c;下图为目前已经收集到的问题一二数据集&#xff0c;本文将为大家详细的介绍具体收集数据方式以及处理方式。 通过网盘分享的文件&#xff1a;分享数据集 …...

手写 vue 源码 === ref 实现

目录 响应式的基本实现 Proxy 与属性访问器 Proxy 的工作原理 属性访问器&#xff08;Getter/Setter&#xff09; 为什么解构会丢失响应性 ref 和 toRefs 的解决方案 proxyRefs&#xff1a;自动解包 ref 总结 Vue3 的响应式系统是其核心特性之一&#xff0c;它通过 Pro…...

Python爬虫抓取Bilibili弹幕并生成词云

1. 引言 Bilibili&#xff08;B站&#xff09;是国内知名的视频分享平台&#xff0c;拥有海量的弹幕数据。弹幕是B站的核心特色之一&#xff0c;用户通过弹幕进行实时互动&#xff0c;这些数据对于分析视频热度、用户情感倾向等具有重要价值。 本文将介绍如何利用Python爬虫技…...

【Python 字典(Dictionary)】

Python 中的字典&#xff08;Dictionary&#xff09;是最强大的键值对&#xff08;key-value&#xff09;数据结构&#xff0c;用于高效存储和访问数据。以下是字典的核心知识点&#xff1a; 一、基础特性 键值对存储&#xff1a;通过唯一键&#xff08;Key&#xff09;快速访…...

k8s之探针

探针介绍&#xff1a; 编排工具运行时&#xff0c;虽说pod挂掉会在控制器的调度下会重启&#xff0c;出现pod重启的时候&#xff0c;但是pod状态是running,无法真实的反应当时pod健康状态&#xff0c;我们可以通过Kubernetes的探针监控到pod的实时状态。 Kubernetes三种探针类…...

upload-labs靶场通关详解:第三关

一、分析源代码 代码注释如下&#xff1a; <?php // 初始化上传状态和消息变量 $is_upload false; $msg null;// 检查是否通过POST方式提交了表单 if (isset($_POST[submit])) {// 检查上传目录是否存在if (file_exists(UPLOAD_PATH)) {// 定义禁止上传的文件扩展名列表…...

LeetCode:101、对称二叉树

递归法&#xff1a; /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right) {…...

zst-2001 历年真题 UML

UML - 第1题 ad UML - 第2题 依赖是暂时使用对象&#xff0c;关联是长期连接 依赖&#xff1a;依夜情 关联&#xff1a;天长地久 组合&#xff1a;组一辈子乐队 聚合&#xff1a;好聚好散 bd UML - 第3题 adc UML - 第4题 bad UML - 第5题 d UML - 第6题 …...

对称加密以及非对称加密

对称加密和非对称加密是两种不同的加密方式&#xff0c;它们在加密原理、密钥管理、安全性和性能等方面存在区别&#xff0c;以下是具体分析&#xff1a; 加密原理 对称加密&#xff1a;通信双方使用同一把密钥进行加密和解密。就像两个人共用一把钥匙&#xff0c;用这把钥匙锁…...

Java反射 八股版

目录 一、核心概念阐释 1. Class类 2. Constructor类 3. Method类 4. Field类 二、典型应用场景 1. 框架开发 2. 单元测试 3. JSON序列化/反序列化 三、性能考量 四、安全与访问控制 1. 安全管理器限制 2. 打破封装性 3. 安全风险 五、版本兼容性问题 六、最佳…...

C++跨平台开发实践:深入解析与常见问题处理指南

一、跨平台开发基础架构设计 1.1 跨平台架构的核心原则 分层设计模式&#xff1a; 平台抽象层(PAL)&#xff1a;将平台相关代码集中管理 核心逻辑层&#xff1a;完全平台无关的业务代码 平台实现层&#xff1a;针对不同平台的特定实现 代码组织最佳实践&#xff1a; pro…...

【“星睿O6”AI PC开发套件评测】+ MTCNN 开源模型部署和测试对比

经过了前几篇文章的铺垫&#xff0c;从搭建 tensorflow 开发环境&#xff0c;到测试官方 onnx 模型部署到 NPU&#xff0c;接着部署自己的 mnist tensorflow 模型到 NPU。这是一个从易到难的过程&#xff0c;本篇文章介绍开源复杂的人脸识别模型 mtcnn 到 “星睿O6” NPU 的部署…...

JAVA实战开源项目:装饰工程管理系统 (Vue+SpringBoot) 附源码x

本文项目编号 T 179 &#xff0c;文末自助获取源码 \color{red}{T179&#xff0c;文末自助获取源码} T179&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…...

centos 7 安装 java 运行环境

centos 7 安装 java 运行环境 java -version java version "1.8.0_131" Java(TM) SE Runtime Environment (build 1.8.0_131-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)java -version java version "1.8.0_144" Java(TM) …...

力扣题解:21.合并两个有序链表(C语言)

将两个升序链表合并为一个新的升序链表是一个经典的链表操作问题。可以通过递归或迭代的方法来解决。以下是解释和代码实现&#xff1a; 递归&#xff1a; 每次比较两个链表的头节点&#xff0c;将较小的节点添加到新链表中&#xff0c;并递归处理剩余部分。 截至条件&#xf…...

iOS App 安全性探索:源码保护、混淆方案与逆向防护日常

iOS App 安全性探索&#xff1a;源码保护、混淆方案与逆向防护日常 在 iOS 开发者的日常工作中&#xff0c;我们总是关注功能的完整性、性能的优化和UI的细节&#xff0c;但常常忽视了另一个越来越重要的问题&#xff1a;发布后的应用安全。 尤其是对于中小团队或独立开发者&…...

SpringBoot默认并发处理(Tomcat)、项目限流详解

SpringBoot默认并发处理 在 Spring Boot 项目中&#xff0c;默认情况下&#xff0c;同一时间能处理的请求数由​​内嵌的 Tomcat 服务器​​的线程池配置决定。 默认并发处理能力​ 请求处理流程​ 请求到达​​&#xff1a;新请求首先进入 TCP 连接队列&#xff08;最大 ma…...

Xterminal(或 X Terminal)通常指一类现代化的终端工具 工具介绍

Xterminal&#xff08;或 X Terminal&#xff09;通常指一类现代化的终端工具&#xff0c;旨在为开发者、运维人员提供更高效、更智能的命令行操作体验。 &#x1f4e2;提示&#xff1a;文章排版原因&#xff0c;资源链接地址放在文章结尾&#x1f447;&#x1f447;&#xff…...

如何把win10 wsl的安装目录从c盘迁移到d盘

标题&#xff1a;如何把win10 wsl的安装目录从c盘迁移到d盘 通过microsoft store安装的 wsl 目录默认在 C:\Users[用户名]\AppData\Local\wsl 下 wsl的docker镜像以及dify的编译环境会占用大量硬盘空间&#xff0c;0.15.3 、1.1.3、1.3.1 三个版本的环境占用空间超过40GB [图…...

2025医疗信息化趋势:健康管理系统如何重构智慧医院生态

当北京协和医院的门诊大厅启用智能分诊机器人时&#xff0c;距离其3000公里外的三甲医院正通过健康管理系统将慢性病复诊率降低42%。这场静默发生的医疗革命&#xff0c;正在重新定义2025年智慧医院的建设标准。 一、穿透数据孤岛的三大核心引擎 最新版《智慧医院评价指标体系…...

java volatile关键字

volatile 是 Java 中用于保证多线程环境下变量可见性和禁止指令重排序的关键字。 普通变量不加volatile修饰有可见性问题&#xff0c;即有线程修改该变量值&#xff0c;其他线程无法立即感知该变量值修改了。代码&#xff1a; private static int intVal 0; // 普通变量未加 …...

中阳策略模型:结构节奏中的方向感知逻辑

中阳策略模型&#xff1a;结构节奏中的方向感知逻辑 在交易世界中&#xff0c;“节奏”与“结构”的互动远比大多数人想象得复杂。中阳研究团队在大量实战数据分析中提出一个核心观点&#xff1a;方向感的建立&#xff0c;必须以结构驱动为前提&#xff0c;以节奏确认为依据。 …...