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

Synchronized详解及高频面试问答

目录

JVM简述

Synchronized详解及面试高频问答

而synchronized是什么,可以解决什么问题?

synchronized怎么使用?

锁升级升级了什么?

为什么要这样做锁升级?

锁升级的过程是怎样的?为什么会有偏向锁,轻量级锁,重量级锁?

为什么会有偏向锁呢?

什么时候升级到轻量级锁?

为什么要有轻量级锁呢?

自旋的性能一定要比阻塞的性能好吗?

那轻量级锁什么时候升级为重量级锁呢?

为什么要升级到重量级锁?

为什么要有锁监视器呢?

Synchronized的可重入锁如何实现?

锁池与等待池的作用?


想要了解Synchronized,需要先了解JVM(Java内存模型)

JVM简述

Java内存模型将内存分为两种,主内存工作内存。

并且规定,所有的变量都存储在主内存中(不包括局部变量与方法参数)。

主内存中的变量是所有线程共享的。

每个线程都有自己的工作内存,存储的是当前线程所使用到的变量值。主内存变量中的一个副本数据。

线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。

不同线程间无法直接访问对方工作内存中的变量。

线程间变量值的传递需要通过主内存实现。

这样规定的原因:

是为了屏蔽各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果。

关于各种硬件间的内存访问差异

CPU,内存,IO设备都在不断迭代,不断朝着更快的方向努力,但三者的速度是有差异的。

CPU最快,内存其次,IO设备(硬盘)最慢。

为了合理利用CPU的高性能,平衡三者间的速度差异,计算机体系结构,操作系统,编译系统都做了贡献,主要体现为:

  • CPU增加了缓存,以平衡与内存的速度差异,且分为三级缓存,一级和二级缓存是CPU核心私有的,但是第三级缓存是共享的。

这样CPU运算时所需要的变量,优先会从缓存中读取。

缓存没有时,会从主内存中加载并缓存。如下图所示:

image-20250509163155756

事物都是有两面性的,缓存提高了CPU的运算速度,也带来了相应的问题:

当多个线程在不同的CPU上运行并访问同一个变量时,由于缓存的存在,可能读取不到做最新的值,也就是可见性问题。

可见性指的是一个线程对共享变量的修改,另一个线程能够立刻看到,被称为可见性

  • 操作系统增加了进程线程,以时分复用CPU,进而均衡CPU与IO设备的速度差异

操作系统通过任务的一个切换来减少CPU的等待时间,从而提高效率。

任务切换的时间,可能是发生在任何一条CPU指令执行完之后。

image-20250509163325242

但是我们平时使用的编程语言,如C,Java,Python等都是高级语言,高级语言转换成CPU指令时,一条指令可能对应多条CPU指令。 相当于1=n,这是违背我们直觉的地方。

所以问题来了,著名的count+=1问题就是这个原因。也就是原子性问题。

我们把一个或多个操作在CPU执行的过程中不被中断的特性为原子性。(这里的操作是指我们高级语言中相应的一些操作)

  • 编译程序优化指令执行次序,使得缓存能够得到更加合理的利用。

指令重排序可以提高了缓存的利用率,同样也带来了有序性问题

也就是单例模式问题

重排序提高缓存利用率的例子:

在平时写代码时,经常会在方法内部的开始位置,把这个方法用到的变量全部声明了一遍。缓存的容量是有限的,声明的变量多的时候 前面的变量可能就会在缓存中失效 。

接下来再写业务时,用到了最先声明的变量 然后发现在缓存中已经失效了,需要重新的去主内存进行加载。

所以指令重排序可以看成编译器对我们写的代码进行的一个优化。就类似于让变量都能用上,不至于等到失效在使用。

所以要想实现在各种平台都能达到一直的内存访问效果,就需要解决硬件和操作系统之间产生的问题:

1.CPU增加缓存最后导致的可见性问题

2.操作系统增加了线程,进程之后出现的原子性问题

3.指令重排序导致的有序性问题

Java内存模型如何解决三个问题?

原子性问题解决方案

  • JVM定义了8种操作来完成主内存与工作内存之间的数据交互,虚拟机在实现时需要保证每一种操作都是原子的,不可再分的。

Java中基本数据类型的访问、读写都是具备原子性的(long和Double除外),更大的原子性保证:Java提供了synchronized关键字(synchronized的字节码指令monitor enter和monitor exit来隐式的使用了lock和unlock操作),在synchronized块之间的操作也具备原子性。

八种操作: lock,unlock,read,load,assign,use,store,write

CAS(乐观锁),比较并替换,(Compare And Swap),CAS是一条CPU的原子指令(即cmpxchg指令),Java中的Unsafe类提供了相应的CAS方法,如(compareAndSwapXXX)底层实现即为CPU指令cmpxchg,从而保证操作的原子性。

可见性问题与有序性问题解决方案

  • JVM定义了Happens-Before原则来解决内存的不可见性与重排序的问题。

Happens-Before规则约束了编译器的优化行为,虽允许编译器优化,但是要求编译器优化后要遵守Happens-Before规则。

Happens-Before规则:

对于两个操作A和B,这两个操作可以在不同的线程中执行,如果A Happens-Before B,那么可以保证,当A操作执行完后,A操作的执行结果对B操作时可见的。

8种Happens-Before规则

程序次序规则、锁定规则、volatile变量规则、线程启动规则、线程终止规则、线程中断规则、对象终结原则、传递性原则。

volatile变量规则(重点):对一个volatile变量的写操作先行发生于后面的这个变量的读操作。

Synchronized详解及面试高频问答

而synchronized是什么,可以解决什么问题?

synchronized就是锁,能保证某段代码同一时间只能被拿到锁的线程访问,这就保证了原子性。

synchronized编译之后就是monitor entermonitor exit两个指令。

monitor enter就是 加锁(lock),加锁的时候会使用读屏障,强行去从主内存中重新读取数据,也就是说他能保证读到的数据都是最新的数据。

monitor exit就是 解锁(unlock)。 解锁时通过写屏障保证强制将CPU缓存中的变量刷新到主内存中,能够保证线程修改后的数据对其他线程立即可见,这就是保证了可见性

synchronized能够通过内存屏障防止指令重排,这就保证了有序性

synchronized怎么使用?

synchronized修饰普通方法锁的就是this(当前对象),也就是说一个对象用一把锁,修饰静态方法锁 的就是类.class对象(类的字节码对象),也就是类的所有对象共用一把锁。

synchronized修饰代码块,那就是代码块中写什么就锁什么。

Synchronized在JDK1.6时做了锁升级以提高Synchronized锁的性能。

Synchronized加锁的原理其实是调用操作系统底层原语mutex。

然后又涉及了线程的阻塞与唤醒,Java线程模型是一对一的,每一个Java线程都直接对应一个操作系统的内核级线程,每次切换线程都需要操作系统从用户态切换到内核态,消耗的性能很大。这也就是JDK1.6版本前Synchronized的问题所在

锁升级升级了什么?

在低并发的情况下,锁竞争比较少的情况下,不让其阻塞线程,只要线程不阻塞,操作系统就不需要从用户态切换到内核态,提高性能。

在高并发,锁竞争较为激烈的情况下,再让其去阻塞线程。

锁升级的过程:无锁 --->偏向锁---> 轻量级锁---> 重量级锁

为什么要这样做锁升级?

在实际开发中,一个系统大多数的时候都是不存在锁竞争的,经常就只有一两个线程去拿锁。

例如:

商城系统24小时运行,从凌晨一点到早上六点这段时间不会有太多人会购物,这段时间是没有锁竞争的。

高并发的时候往往发生在固定的时间点,其他时间并发量都不大。所以绝大多数系统没什么并发量。

即便是高并发系统,也不时时刻刻有高并发,绝大多数时间其实都只有一个或者几个线程进行锁竞争,

为了在低并发的时候降低获取锁的代价,为了提高低并发时的性能,所以做了锁升级。

锁升级的过程其实是为了应付越来越激烈的锁竞争的过程。

锁升级的过程是怎样的?为什么会有偏向锁,轻量级锁,重量级锁?

最开始我们的系统是无锁状态,当有第一个线程来访问同步代码块时,JVM将对象头的Mark Word锁标志位设置为偏向锁。

然后将线程ID记录到Mark Word中,这是线程进入同步代码块,就不需要其他的同步操作了,性能得到了极大的提高。

为什么会有偏向锁呢?

偏向锁考虑的是只有一个线程抢锁的场景

什么时候升级到轻量级锁?

当有第二个线程来抢锁的时候就升级为轻量级锁,第二个线程拿不到锁就采用CAS加自旋的方式不断重新尝试获取锁。

为什么要有轻量级锁呢?

轻量级锁考虑的是竞争锁的线程不多,而且线程持有锁的时间也不长的一个场景。

因为阻塞线程需要操作系统从用户态切换到内核态,性能消耗较大,如果刚阻塞了这个线程,紧接着这个锁就被释放了,这会造成性能的损耗,且得不偿失。

因此在轻量级锁期间直接不阻塞线程,让其自旋等待锁释放。

自旋的性能一定要比阻塞的性能好吗?

自旋是让线程一直循环执行抢锁命令,线程一直在运行,他没有被阻塞,所以就减少了线程上下文切换的一个开销,操作系统不需要切换到内核态了,短时间的自旋性能是不错的。

但长时间的自旋会让CPU一直在空转,CPU没有办法去执行其他任务,会浪费CPU,所以这里轻量级锁只是在两个线程竞争的场景下使用。

且这里的自旋是适应性自旋,自旋的时间由上一个线程自旋的时间去决定。

可以知悉,在偏向锁期间只记录线程ID,而轻量级锁只是自旋抢锁,它们都没有去做操作系统级的线程阻塞与切换,不需要操作系统切换到内核态去做操作,整个过程在用户态操作即可,所以在较低的锁竞争时,偏向锁与轻量级锁的设计就提高了性能。

而在系统中绝大所数的时候锁竞争其实是比较低的。

那轻量级锁什么时候升级为重量级锁呢?

当第二个线程自旋到一定次数之后还是没拿到锁或获取锁失败,或者当有不少其他的线程来抢锁了,那就升级为重量级锁。

就需要调用操作系统的底层原语mutex,所以每次切换线程都需要操作系统从用户态转换成内核态,性能损耗很大。(这也是称为重量级锁的原因)

为什么要升级到重量级锁?

因为自璇只适合锁竞争比较小、而且执行时间比较短的一个程序,但如果有大量的线程去抢夺锁,就需要大量的线程去自旋,这样十分浪费CPU的算力。

当某个线程执行任务的时间非常长,那么其他线程自旋的时间也会被无限拉长,直至任务完成,锁释放,长时间的自旋会导致会让CPU一直空转,让CPU无法执行其他任务,浪费CPU的算力。

所以当第二个线程自旋到一定次数之后还是没拿到锁或获取锁失败,或者当有不少其他的线程来抢锁的时候,就需要直接进入重量级锁了。

将那些没有拿到锁的线程阻塞,这时候操作系统由用户态切换成内核态时的性能损耗没有多个线程自旋的性能损耗大

当升级到重量级锁时,对象头的 Mark Word 的指针会指向锁监视器 monitor。

为什么要有锁监视器呢?

锁监视器主要用来负责记录锁的拥有线程,记录锁的重入次数,负责线程的阻塞唤醒。

具体来说锁监视器就是一个对象,有以下几个重要属性

 class ObjectMonitor{void* _owner;// 持有锁的线程WaitSet _WaitSet;// 等待池 (管理调用wait()方法的线程)EntryList _EneryList;// 锁池(管理因竞争锁失败而阻塞的线程)int _recursions;// 记录锁的重入次数//其他不重要的字段};

owner字段:记录持有锁的线程。

重入次数计数器:当一个线程重复的去获取这个锁,这就是可重入锁(ReentrantLock)。

Synchronized的可重入锁如何实现?

就是依赖锁监视器内部的重入次数计数器,重入一次计数器加一次,释放一次计数器减一次,减到零就完全释放锁了。

锁池与等待池的作用?

首先在重量级锁状态,当有线程拿到锁,此时监视器的owner字段就记录拿到锁的线程,没有拿到锁的线程就会被阻塞住,进入blocking(阻塞)状态,然后放在锁池中。

当拿到锁的线程调用了wait方法,那该线程就释放锁,进入waiting(等待)状态,然后放在等待池中。

当某个线程调用了notify()方法唤醒了在等待池中的某个线程,那这个线程就从waiting状态变成blocking状态,然后再被放进锁池中,等待锁释放,重新去抢锁。

锁竞争失败的线程和调用了wait方法的线程的区别是什么?为什么要分开放在两个不同的集合中?

锁池放的是竞争锁失败的线程,线程状态是blocking,在这个集合中的线程目标是尽快获取锁去执行任务,这是锁的互斥问题。

等待池中放的是主动放弃锁的线程,这个集合中的线程等待被其他线程唤醒之后去配合其他线程去完成某项任务。线程状态是waiting或time waiting。这些waiting状态的线程事项等待某种资源到位或者某项任务完成之后,再被notify()方法唤醒,再放入锁池中,准备去抢锁做业务。这是线程通信问题。

所以等待池中的线程与锁池中的线程的目标与解决的问题截然不同。自然要放在两个不同的集合中了。

希望对大家有所帮助!

相关文章:

Synchronized详解及高频面试问答

目录 JVM简述 Synchronized详解及面试高频问答 而synchronized是什么,可以解决什么问题? synchronized怎么使用? 锁升级升级了什么? 为什么要这样做锁升级? 锁升级的过程是怎样的?为什么会有偏向锁&…...

【LLIE专题】基于码本先验与生成式归一化流的低光照图像增强新方法

GLARE: Low Light Image Enhancement via Generative Latent Feature based Codebook Retrieval(2024,ECCV) 专题介绍一、研究背景二、GLARE方法阶段一:正常光照代码本学习(Normal-Light Codebook Learning&#xff09…...

26考研 | 王道 | 计算机组成原理 | 一、计算机系统概述

26考研 | 王道 | 计算机组成原理 | 一、计算机系统概述 文章目录 26考研 | 王道 | 计算机组成原理 | 一、计算机系统概述1.1 计算机的发展1.2 计算机硬件和软件1.2.1 计算机硬件的基本组成1.2.2 各个硬件的工作原理1.2.3 计算机软件1.2.4 计算机系统的层次结构1.2.5 计算机系统…...

Linux云计算训练营笔记day08(MySQL数据库)

Linux云计算训练营笔记day08(MySQL数据库) 目录 Linux云计算训练营笔记day08(MySQL数据库)数据准备修改更新update删除delete数据类型1.整数类型2.浮点数类型(小数)3.字符类型4.日期5.枚举: 表头的值必须在列举的值里选择拷贝表复…...

从基础到实习项目:C++后端开发学习指南

在当今技术快速迭代的背景下,后端开发作为软件工程的核心支柱持续发挥着关键作用。C凭借其卓越的性能表现和系统级控制能力,依然是构建高性能后端服务的首选语言之一。本文将系统性地解析现代C后端开发的核心技术体系,包括从语言特性精要到架…...

jedis+redis pipeline诡异的链接损坏、数据读取异常问题解决

文章目录 问题现象栈溢出(不断的重连)读取超时未知响应尝试读取损坏的链接读取到的数据和自己要读的无关,导致空指针、类型转换错误,数据读取错乱 问题写法问题分析修复注意点 问题现象 栈溢出(不断的重连&#xff09…...

十、HQL:排序、联合与 CTE 高级查询

作者:IvanCodes 日期:2025年5月15日 专栏:Hive教程 Apache Hive 作为大数据领域主流的数据仓库解决方案,其查询语言 HQL (Hive Query Language) 是数据分析师和工程师日常工作的核心。除了基础的 SELECT-FROM-WHERE,HQ…...

数据结构—排序(斐波那契数列,冒泡,选择,插入,快速,归并,图,广度优先算法)

目录 一 斐波那契数列(递归算法) 定义 原理 二 冒泡排序 定义 排序思路 函数原型 参数详解: 算法分析: 1. 使用函数库的qsort函数 2. 自定义冒泡排序 三 选择排序 定义 排序思路 四 插入排序 定义 排序思路 五 快速…...

NetSuite CSV导入Item Fulfillment的功能测试

上一篇我们说过如何通过CSV导入更新IF上的Department/Class信息,这篇是来测试一下如果SO在Pending Fulfillment的状态下通过CSV导入IF,这个新版本的一个功能,刚好将测试的过程与结果与大家分享~ 准备文件 External ID是外部ID; …...

网络原理 | 网络基础概念复习

目录 网络中的重要概念 IP地址 端口号 协议 五元组 协议分层 OSI七层网络模型 TCP/IP 五层(四层)模型 网络设备所在的分层 封装和分用 网络中的重要概念 IP地址 IP地址主要用于标识网络主机、其他网络设备的网络地址。在网络数据传输中&#…...

Vsan数据恢复——Vsan上虚拟机不可用,虚拟机组件信息破坏的数据恢复

Vsan数据恢复环境: 一台采用VsSAN分布式文件系统的存储设备由于未知原因关机重启。管理员发现上层的虚拟机不可用,存储内的数据丢失。 Vsan数据恢复过程: 1、将故障存储设备断电,将存储内的硬盘编号后取出。硬件工程师检测后没有发…...

V837s-LAN8720A网口phy芯片调试

目录 前言 一、LAN8720A 芯片概述 二、硬件连接 三、设备树配置 四、内核配置 五、网口调试 总结 前言 在嵌入式系统开发中,网络连接是至关重要的一部分。v837s开发板搭载了LAN8720A系列的网口PHY芯片,用于实现以太网连接。在开发过程中,对于网口的稳定性和性能的调试至…...

C++(12):using声明

目录 一、定义 二、核心用法示例 示例 1:单独引入 std::string 和 std::coun 示例 2:在局部作用域中使用 using 声明 三、对比 using namespace std(不推荐) 四、关键注意事项 1. 名称冲突问题 2. 作用域规则 3. 头文件中的陷阱 五、最佳实践总结 六、完整安全示…...

Xinference 命令大全:从模型部署到管理

Xinference 是一个高性能、分布式的模型推理框架,支持多种大语言模型(LLM)、嵌入模型(Embedding)和图像生成模型。本文将详细介绍 Xinference 的常用命令,涵盖模型启动、管理、监控及 API 调用,帮助你快速掌握其核心功能。 1. 安装与启动 Xinference 1.1 安装 Xinferen…...

如何在线免费压缩PDF文档?

PDF文件太大,通常是因为内部嵌入字体和图片。怎么才能将文件大小减减肥呢,主要有降低图片清晰度和去除相关字体两个方向来实现文档效果。接下来介绍三个免费压缩PDF实用工具。 (一)iLoveOFD在线转换工具 iLoveOFD在线转换工具&a…...

在Rocky Linux 9.5上部署MongoDB 8.0.9:从安装到认证的完整指南

mongodb 的部署 #安装依赖 yum -y install libcurl openssl #安装mongodb yum -y install https://repo.mongodb.org/yum/redhat/9/mongodb-org/8.0/x86_64/RPMS/mongodb-org-server-8.0.9-1.el9.x86_64.rpm #启动服务 systemctl start mongod.service && system…...

Unix Bourne Shell

本文来源 : 腾讯元宝 Unix Bourne Shell(简称sh)是Unix系统中最经典的命令行解释器(shell),由Stephen Bourne于1977年在贝尔实验室开发,并成为后续众多shell(如bash、ksh等&#xff…...

如何在 AWS 上构建支持 AVIF 的前端图片优化方案

一、为什么使用 AVIF 图片格式? 优势点 说明 高压缩率 在相似质量下,AVIF 文件比 JPEG/PNG/WebP 更小,能有效节省带宽和存储空间。 更高画质 即使在低码率下也能保持清晰细节,减少压缩带来的马赛克或模糊问题。 支持透明度 …...

Linux系统进行环境开发环境配置

一. 使用fishros(鱼香肉丝)配置开发环境 对于初学者来说,最难的关卡莫非是开发环境的的搭建,特别是在Ubuntu系统上ROS系统安装时后出现的各种报错以及失败,本篇博客讲述了ROS系统的一键安装过程,适用于18.04及以后的Ubuntu系统版本…...

前端npm的核心作用与使用详解

一、npm是什么? npm(Node Package Manager) 是 Node.js 的默认包管理工具,也是全球最大的开源代码库生态系统。虽然它最初是为 Node.js 后端服务设计的,但如今在前端开发中已成为不可或缺的基础设施。通过npm,开发者可以轻松安装、管理和共享代码模块。 特性: 依赖管理…...

软考软件评测师——软件工程之系统维护

一、系统质量属性 可维护性 衡量软件系统适应修改的难易程度,包括修复缺陷、扩展功能或调整规模的效率。计算公式为:系统可用时间占比 1/(1平均修复时间),其中平均修复时间(MTTR)指排除故障所需的平均耗时。 可靠性 vs 可用性 可靠性&…...

CSRF攻击 + 观测iframe加载时间利用时间响应差异侧信道攻击 -- reelfreaks DefCamp 2024

参考: https://0x90r00t.com/2024/09/30/3708/ 题目信息 有些事情最好还是保持低调。当然,除非你是个真正的怪胎。 注意:该网站通过HTTPS提供服务 标志格式:DCTF{}题目实现了一个类似视频网站的东西 在其提供的数据库中…...

火山RTC 8 SDK集成进项目中

一、SDK 集成预备工作 1、SDK下载 https://www.volcengine.com/docs/6348/75707 2、解压后 3、放在自己项目中的位置 1)、include 2)、lib 3)、dll 暂时,只需要VolcEngineRTC.dll RTCFFmpeg.dll openh264-4.dll, 放在intLive2…...

spring boot Controller 和 RestController 的区别

spring boot Controller 和 RestController 的区别 5.3.1常用注解 Spring MVC控制器中常使用的注解有如下几种。 Controller Controller 标记在类上。使用Controller 标记的类表示是Spring MVC的Controller对象。分发处理器将会扫描使用了该注解的类,并检测其中的…...

mavgenerate 在 win11 下环境搭建注意问题

开发随笔 mavgenerate 是mavlink配套的协议生成工具,mavgenerate 在 win11 下环境搭建注意问题: 1、Python 就使用文件包当中的版本,由于python 版本能与 future 及 pip 之间存在特定的组合关系,故不推荐下载使用最新版本 2、安…...

SSM项目集成redis、Linux服务器安装redis

在SSM(Spring Spring MVC MyBatis)项目中引入Redis主要分为以下步骤,确保配置正确并能在业务中灵活使用: 1. 添加Redis依赖​​ 在Maven的pom.xml中添加Spring Data Redis和Jedis(或Lettuce)依赖&#…...

sqli-labs靶场第七关——文件导出注入

一:目标 通过sql注入将php代码写入网站目录,通过这个php文件执行命令 二:确认前置条件 %secure_file_priv% 首先我们需要Mysql是否允许导出文件 先尝试在网页中sql注入,检查导出权限 ?id1)) union select 1,secure_file_pr…...

python使用matplotlib无法显示中文字体报错

python使用matplotlib字体报错 当我们使用python使用matplotlib总是出现报错,图片中文变成方框 findfont: Font family WenQuanYi Micro Hei not found. findfont: Font family Heiti TC not found. findfont: Font family [SimHei] not found. Falling back to De…...

VTEP是什么

VTEP(VXLAN Tunnel Endpoint,VXLAN 隧道端点)是 VXLAN(Virtual Extensible LAN)网络中的关键组件,用于处理 VXLAN 流量的封装和解封装。以下以可读的 Markdown 格式详细解释 VTEP 的定义、功能、实现方式以…...

React Native简介

React Native 是由 Meta(原 Facebook)开源的跨平台移动应用开发框架,基于 React 和 JavaScript,允许开发者使用同一套代码库构建 iOS 和 Android 原生应用。通过 JavaScript 调用原生组件实现高性能渲染。 跨平台开发 共享 80%-9…...

边缘计算模块

本文来源 :腾讯元宝 边缘计算模块是一种部署在网络边缘(靠近数据源)的集成化硬件/软件设备,用于实时处理本地数据,减少云端依赖,提升响应速度与安全性。以下是其核心要点: ​​1. 核心组成​​ …...

策略模式-枚举实现

策略模式的实现方法有很多,可以通过策略类if,else实现。下面是用枚举类实现策略模式的方法。 定义一个枚举类,枚举类有抽象方法,每个枚举都实现抽象方法。这个策略,实现方法是工具类的很实现,代码简单好理解 枚举实现…...

C++算法(22):二维数组参数传递,从内存模型到高效实践

引言 在C程序设计中,二维数组的参数传递是许多开发者面临的棘手问题。不同于一维数组的相对简单性,二维数组在内存结构、类型系统和参数传递机制上都存在独特特性。本文将深入探讨静态数组、动态数组以及STL容器三种实现方式,通过底层原理分…...

LeetCode LCR 015. 找到字符串中所有字母异位词 (Java)

LCR 015. 找到字符串中所有字母异位词 题目描述 给定两个字符串 s 和 p,要求找到 s 中所有是 p 的变位词(字母相同但排列不同)的子串,并返回这些子串的起始索引。例如: 输入 s "cbaebabacd", p "a…...

幼儿学前教育答辩词答辩技巧问题答辩自述稿

### 📘《幼儿园大班活动开展存在的问题及解决策略》📝 我的论文题目是《幼儿园大班活动开展存在的问题及解决策略》📖。我将从论文框架、研究内容、需要解决的问题、研究结论这四部分来阐述我的论文📝。 论文框架由绪论&#x1f4…...

双目立体视觉

文章目录 1,前言2,原理3,组成部分3.1,数字图像采集。3.2 ,相机标定。3.3,图像预处理与特征提取。3.4 ,图像校正。3.5 ,立体匹配。3.6 ,三维重建。 4,主要的算…...

机器人弧焊二八混合气体节约

焊接技术在现代工业生产中作为关键环节之一,其效率和成本直接影响到整个制造流程的经济性与环保性。近年来,随着节能减排理念深入人心,各行业都在积极探索绿色制造方案。在焊接领域,二八混合气体的应用结合WGFACS智能流量调节系统…...

Linux进程通讯和原子性

在Linux系统中,进程间通信(IPC)和原子性是并发编程中的核心问题。以下是对这些概念的详细分步解释: 一、进程间通信(IPC)方法 1. 管道(Pipe) 匿名管道:用于父子进程等有…...

深度学习之用CelebA_Spoof数据集搭建一个活体检测-一些模型训练中的改动带来的改善

实验背景 在前面的深度学习之用CelebA_Spoof数据集搭建一个活体检测-模型搭建和训练,我们基于CelebA_Spoof数据集构建了一个用SqueezeNe框架进行训练的活体2D模型,采用了蒸馏法进行了一些简单的工作。在前面提供的训练参数中,主要用了以下几…...

Oracle APEX IR报表列宽调整

1. 问题:如何调整Oracle APEX IR报表列宽 1-1. 防止因标题长而数据短,导致标题行的文字都立起来了,不好看。 1-2. 防止因数据太长而且中间还没有空格,把列撑开的太宽也不换行,不好看。 2. 解决办法 针对如上问题解…...

6大核心记忆方法

以下是结合脑科学原理和高效学习策略总结的 6大核心记忆方法,帮助你摆脱“学完就忘”的困境: 一、间隔重复与分散学习 遵循艾宾浩斯遗忘曲线:学习后20分钟遗忘58%,1天后遗忘66%。通过设定复习节点(如学后1天、3天、1周…...

conda更换清华源

1、概览 anaconda更换速度更快、更稳定的下载源,在linux环境测试通过。 2、conda源查看 在修改之前可以查看下现有conda源是什么,查看conda配置信息,如下: cat ~/.condarc 可以看到你的conda源,以我的conda源举例&am…...

5月15日星期四今日早报简报微语报早读

5月15日星期四,农历四月十八,早报#微语早读。 1、中国至越南河内国际道路运输线路正式开通; 2、免签国1,中乌(兹别克斯坦)互免签证协定6月生效; 3、杭州“放大招”支持足球发展:足…...

网络损伤仪功能介绍与应用场景剖析

以下是关于 网络损伤仪(Network Impairment Emulator) 的核心功能介绍及其应用场景的详细说明: 一、网络损伤仪的核心功能 带宽限制(Bandwidth Throttling) 模拟不同网络带宽(如从1Mbps到10Gbps&#xff09…...

超时检测机制和心跳包机制(Heartbeat)

一、超时检测机制 1. I/O 函数超时设置 1.1 select/poll/epoll 的超时参数 select c struct timeval timeout {3, 0}; // 3秒超时 int n select(maxfd1, &readfds, NULL, NULL, &timeout); if (n 0) printf("select timeout\n"); // 超时无事件poll c …...

经典卷积神经网络

目录 经典卷积神经网络 一、卷积神经网络基础回顾 二、LeNet:开启 CNN 先河 三、AlexNet:突破性进展 四、ZFNet:继承与优化 五、GoogLeNet:引入 Inception 模块 六、VggNet:深度与简单结构的融合 七、ResNet&a…...

Reactor模型详解与C++实现

Reactor模型详解与C实现 一、Reactor模型核心思想 Reactor模式是一种事件驱动的并发处理模型,核心通过同步I/O多路复用实现对多个I/O源的监听,当有事件触发时,派发给对应处理器进行非阻塞处理。 关键特征: 非阻塞I/O&#xff…...

观测云产品更新 | 安全监测、事件中心、仪表板AI智能分析等

观测云更新 安全监测 新增 SIEM 功能模块:实时分析企业各类系统(如服务器、应用、网络设备)的日志和事件数据,自动发现潜在威胁,帮助团队迅速定位异常,充分发挥安全监控中枢的作用。 注意:目…...

【HTML】个人博客页面

目录 页面视图​编辑 页面代码 解释&#xff1a; HTML (<body>): 使用了更加语义化的HTML5标签&#xff0c;例如<header>, <main>, <article>, <footer>。文章列表使用了<article>包裹&#xff0c;结构清晰。添加了分页导航。使用了Font…...

OrangePi Zero 3学习笔记(Android篇)10 - SPI和从设备

目录 1. 配置内核 2. 修改设备数 3. 修改权限 4. 验证 Zero 3的板子有2个SPI Master接口&#xff0c;其中SPI0接的是板载16MB大小的SPI Nor Flash&#xff0c;SPI1则是导出到26pin的接口上。 spi和i2c有点不同&#xff0c;spi是直接生成spi虚拟设备&#xff0c;所以在dev里…...