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

深入剖析 Java 的 synchronized 锁升级过程

前言

在 Java 并发编程领域,synchronized关键字堪称保障线程安全的中流砥柱。随着 JDK 版本的迭代演进,synchronized锁的性能优化也在持续推进,其中锁升级机制尤为关键。本文将深度剖析synchronized锁从偏向锁、轻量级锁到重量级锁的升级历程,详细阐述每个状态的含义、适用场景、实现方式、与 JDK 版本的关联,同时对用户态与内核态这两个重要概念进行深入解读。

image.png

一、用户态与内核态

在探讨锁升级之前,明晰用户态与内核态这两个概念至关重要。

1.1 用户态

用户态是应用程序的运行环境,处于操作系统提供的用户空间中。在此状态下,应用程序的资源访问受限,无法直接触碰硬件设备以及操作系统的核心数据结构。用户态下执行的是用户编写的代码,操作系统通过保护与限制机制,防止应用程序对系统造成破坏。

1.2 内核态

内核态是操作系统内核的运行状态,拥有至高无上的权限,能够访问系统的所有资源,涵盖硬件设备、内存等。当应用程序需要执行特权操作,比如访问硬件设备、进行进程间通信时,必须借助系统调用从用户态切换至内核态,由内核来执行这些操作。

1.3 用户态与内核态的切换

用户态与内核态的切换并非无本万利,这一过程需要保存并恢复当前进程的上下文信息,其中包括寄存器的值、程序计数器等。频繁进行这种切换会严重影响性能。在 Java 的锁机制中,减少此类切换次数成为提升性能的核心要点之一。

二、偏向锁

2.1 偏向锁的含义

偏向锁是 JDK 6 引入的一项优化创举,旨在解决仅有一个线程频繁访问同步块时的锁竞争开销问题。其核心思路是,当一个线程首次访问同步块并获取锁时,会在对象头中记录该线程的 ID。此后,该线程再次访问此同步块,无需再进行常规的锁获取操作,仅需检查对象头中的线程 ID 是否与自身一致。若一致,便能直接进入同步块,从而避免了诸如 CAS(Compare and Swap)操作等高开销的锁获取流程。

2.2 业务场景

偏向锁适用于多数时间仅有一个线程访问同步资源的场景。例如在单线程环境中,或者某个线程长时间持有锁的情况。以 Web 应用为例,某些单例对象的初始化和访问操作,若仅在应用启动时由一个线程执行,后续极少被其他线程访问,此时使用偏向锁能够显著提升这部分代码的执行效率。

2.3 实现方式

在 Java 中,对象头是实现偏向锁的关键所在。对象头包含若干标志位以及线程 ID 等信息。当一个线程首次访问同步块并成功获取锁时,JVM 会将对象头中的偏向锁标志位置为 1,并记录当前线程的 ID。后续该线程再次访问同步块时,JVM 会检查对象头中的偏向锁标志位和线程 ID,若两者匹配,线程即可直接进入同步块。

当有其他线程试图访问被偏向锁锁定的对象时,偏向锁会被撤销。在撤销过程中,JVM 会遍历持有该对象的线程栈,检查是否存在该对象的锁记录。若存在,则将偏向锁升级为轻量级锁。

2.4 模拟示例

public class BiasedLockExample {private static final Object lock = new Object();public static void main(String[] args) {// 预热,促使JVM有机会启用偏向锁for (int i = 0; i < 10000; i++) {synchronized (lock) {// 可执行一些简单操作}}Thread thread = new Thread(() -> {long startTime = System.currentTimeMillis();for (int i = 0; i < 1000000; i++) {synchronized (lock) {// 可执行一些简单操作}}long endTime = System.currentTimeMillis();System.out.println("Thread cost time: " + (endTime - startTime) + "ms");});thread.start();try {thread.join();} catch (InterruptedException e) {e.printStackTrace();}}
}

在这个示例中,我们先通过多次循环访问同步块进行预热,为 JVM 启用偏向锁创造条件。随后启动一个线程,在线程中大量访问同步块,通过计算时间来观察偏向锁对性能的影响。

2.5 底层原理

偏向锁的底层实现依赖于对象头中的 Mark Word。Mark Word 是对象头的一部分,用于存储对象的哈希码、锁状态、偏向锁标识等信息。在偏向锁模式下,Mark Word 存储了偏向锁的线程 ID 和偏向锁标志位。当线程访问同步块时,首先检查 Mark Word 中的偏向锁标志位。若标志位为 1 且线程 ID 与当前线程 ID 一致,则可直接进入同步块,无需进行任何锁获取操作。

当有其他线程尝试访问同步块时,偏向锁的撤销步骤如下:

  1. 首先,JVM 暂停拥有偏向锁的线程。
  2. 接着,遍历该线程的栈,查找是否存在该对象的锁记录。
  3. 若存在锁记录,将偏向锁升级为轻量级锁,并清除 Mark Word 中的偏向锁标志位。
  4. 最后,恢复被暂停的线程。

三、轻量级锁

3.1 轻量级锁的含义

轻量级锁是继偏向锁之后引入的锁优化机制,主要用于解决多线程竞争不太激烈场景下的锁性能问题。当多个线程在短时间内交替访问同步块时,偏向锁失效,此时轻量级锁通过 CAS 操作避免了重量级锁带来的用户态与内核态切换的高昂开销。

3.2 业务场景

轻量级锁适用于多线程竞争相对缓和的场景。例如在高并发的 Web 应用中,某些资源可能被多个线程交替访问,但竞争并不激烈。在此种情况下,使用轻量级锁能够规避重量级锁的高开销,提升系统的并发性能。

3.3 实现方式

当一个线程尝试获取轻量级锁时,JVM 会在当前线程的栈帧中创建一个锁记录(Lock Record),并将对象头中的 Mark Word 复制到锁记录中。随后,JVM 尝试使用 CAS 操作将对象头中的 Mark Word 替换为指向锁记录的指针。若 CAS 操作成功,表明该线程成功获取轻量级锁,此时对象头中的 Mark Word 变为指向锁记录的指针,且锁记录中的 owner 字段指向当前线程。

若 CAS 操作失败,意味着已有其他线程获取了该锁。此时,当前线程会尝试自旋(Spin)一定次数,再次尝试获取锁。自旋是指线程在不放弃 CPU 使用权的前提下,不断尝试获取锁,期望在短时间内其他线程能够释放锁。若自旋一定次数后仍无法获取锁,轻量级锁将升级为重量级锁。

3.4 模拟示例

public class LightweightLockExample {private static final Object lock = new Object();public static void main(String[] args) {Thread thread1 = new Thread(() -> {for (int i = 0; i < 1000000; i++) {synchronized (lock) {// 可执行一些简单操作}}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 1000000; i++) {synchronized (lock) {// 可执行一些简单操作}}});long startTime = System.currentTimeMillis();thread1.start();thread2.start();try {thread1.join();thread2.join();} catch (InterruptedException e) {e.printStackTrace();}long endTime = System.currentTimeMillis();System.out.println("Two threads cost time: " + (endTime - startTime) + "ms");}
}

在这个示例中,我们启动两个线程同时访问同步块,模拟多线程竞争不太激烈的场景。通过观察两个线程的总执行时间,对比轻量级锁在此场景下的性能表现。

3.5 底层原理

轻量级锁的底层实现主要依赖于 CAS 操作和自旋机制。在获取轻量级锁时,通过 CAS 操作将对象头中的 Mark Word 替换为指向锁记录的指针。若 CAS 操作失败,说明锁已被其他线程持有。此时,当前线程进行自旋操作,在自旋过程中不断尝试使用 CAS 操作获取锁。

自旋的目的是在短时间内等待其他线程释放锁,避免直接进入重量级锁带来的高开销。自旋次数通常有限,不同的 JVM 实现中,自旋次数的默认值可能有所差异。若自旋一定次数后仍无法获取锁,JVM 会判定竞争较为激烈,进而将轻量级锁升级为重量级锁。

自旋锁什么时候升级成重量级锁

JDK1.6之前:在某一个线程自旋次数超过十次就会升级成重量级锁

JDK1.6之后:自适应自旋,JDK根据线程运行情况自己判断

四、重量级锁

4.1 重量级锁的含义

重量级锁是传统的synchronized锁实现方式,通过操作系统的互斥量(Mutex)实现线程同步。在重量级锁模式下,当一个线程尝试获取锁时,若锁已被其他线程持有,当前线程会被阻塞,进入等待队列,等待操作系统的调度。这种方式会导致用户态与内核态的频繁切换,从而产生较高的性能开销。

4.2 业务场景

重量级锁适用于多线程竞争极为激烈的场景。例如在需要大量并发访问共享资源的场景中,当轻量级锁和偏向锁无法满足需求时,便会升级为重量级锁。以大型分布式系统为例,多个节点同时访问共享的数据库资源,竞争激烈,此时可能会采用重量级锁来确保数据的一致性。

4.3 实现方式

在 Java 中,当轻量级锁升级为重量级锁时,JVM 会在对象头中设置一个指向重量级锁(Monitor)的指针。Monitor 是操作系统提供的同步机制,包含一个等待队列和一个入口队列。当一个线程尝试获取锁时,若锁已被其他线程持有,该线程会被放入 Monitor 的等待队列中,进入阻塞状态。当持有锁的线程释放锁时,会从等待队列中唤醒一个线程,使其有机会获取锁。

4.4 模拟示例

public class HeavyweightLockExample {private static final Object lock = new Object();public static void main(String[] args) {Thread[] threads = new Thread[10];for (int i = 0; i < 10; i++) {threads[i] = new Thread(() -> {for (int j = 0; j < 1000000; j++) {synchronized (lock) {// 可执行一些简单操作}}});}long startTime = System.currentTimeMillis();for (Thread thread : threads) {thread.start();}for (Thread thread : threads) {try {thread.join();} catch (InterruptedException e) {e.printStackTrace();}}long endTime = System.currentTimeMillis();System.out.println("Ten threads cost time: " + (endTime - startTime) + "ms");}
}

在这个示例中,我们启动 10 个线程同时访问同步块,模拟多线程竞争非常激烈的场景。通过观察 10 个线程的总执行时间,了解重量级锁在此场景下的性能表现。

4.5 底层原理

重量级锁的底层实现依赖于操作系统的互斥量(Mutex)。当一个线程获取重量级锁时,需通过系统调用进入内核态,请求操作系统分配一个互斥量。若互斥量已被其他线程持有,当前线程会被放入等待队列,进入阻塞状态,此时线程从用户态切换至内核态。

当持有锁的线程释放锁时,会唤醒等待队列中的一个线程。被唤醒的线程会从内核态切换回用户态,尝试获取锁。这种用户态与内核态的频繁切换会带来较高的性能开销,因此在竞争不激烈的情况下,应尽量避免使用重量级锁。

image.png

五、锁升级过程总结

在 Java 中,synchronized锁的升级过程是一个逐步优化的过程。当一个线程首次访问同步块时,JVM 会尝试使用偏向锁提升性能。若有其他线程尝试访问被偏向锁锁定的对象,偏向锁会升级为轻量级锁。当多个线程竞争激烈,轻量级锁的自旋无法在短时间内获取锁时,轻量级锁会升级为重量级锁。

这种锁升级机制能够依据不同的业务场景和线程竞争状况,自动选择最为合适的锁类型,从而有效提升系统的并发性能。在实际开发中,我们应尽量避免不必要的锁竞争,合理运用synchronized关键字,充分发挥锁升级机制的优势。

六、JDK 版本与锁升级

锁升级机制在不同的 JDK 版本中存在差异。在 JDK 6 之前,synchronized锁仅有一种重量级锁的实现方式,性能相对欠佳。从 JDK 6 开始,引入了偏向锁和轻量级锁,极大地提升了synchronized锁的性能。

在后续的 JDK 版本中,锁升级机制持续优化改进。例如,在部分 JDK 版本中,对自旋策略进行了调整,根据不同的硬件环境和线程竞争情况,动态调整自旋次数,进一步提升性能。

在使用synchronized锁时,我们务必关注所使用的 JDK 版本特性,以便更好地利用锁升级机制优化程序性能。

七、总结

本文深度剖析了 Java 中synchronized锁的升级过程,涵盖偏向锁、轻量级锁和重量级锁的含义、业务场景、实现方式、模拟示例以及底层原理。同时,介绍了用户态与内核态的概念及其在锁机制中的作用。通过深入了解锁升级过程,我们能够编写出更为高效的并发程序,提升系统的性能与稳定性。在实际开发中,应依据具体的业务场景和线程竞争情况,合理选择锁的类型,充分发挥 Java 并发编程的优势。

相关文章:

深入剖析 Java 的 synchronized 锁升级过程

前言 在 Java 并发编程领域&#xff0c;synchronized关键字堪称保障线程安全的中流砥柱。随着 JDK 版本的迭代演进&#xff0c;synchronized锁的性能优化也在持续推进&#xff0c;其中锁升级机制尤为关键。本文将深度剖析synchronized锁从偏向锁、轻量级锁到重量级锁的升级历程…...

当文件补丁修改器因为文件操作权限有问题时,可以将文件拷贝到普通目录操作

文章目录 当文件补丁修改器因为文件操作权限有问题时&#xff0c;可以将文件拷贝到普通目录操作概述笔记直接在安装目录打补丁失败的情况将目标程序拷贝到补丁修改器的解压目录打补丁成功的情况备注END 当文件补丁修改器因为文件操作权限有问题时&#xff0c;可以将文件拷贝到普…...

【TCP】rfc文档

tcp协议相关rfc有哪些 TCP&#xff08;传输控制协议&#xff09;是一个复杂的协议&#xff0c;其设计和实现涉及多个RFC文档。以下是一些与TCP协议密切相关的RFC文档列表&#xff0c;按照时间顺序排列&#xff0c;涵盖了从基础定义到高级特性和优化的各个方面&#xff1a; 基…...

Linux探秘坊-------3.开发工具详解(1)

1 初识vim编辑器 创建第一个vim编辑的代码 1.新建文件 2.使用vim打开 3.打开默认是命令模式&#xff0c;写代码需要在屏幕上输出“i”字符 1.写完代码后要按Esc键退出到指令模式2.再按shift:wq即可保存并退出vim &#xff08;因为不支持鼠标&#xff0c;通常 使用键盘上的箭…...

如何在Python中进行JSON数据的序列化和反序列化?

在Python中&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;易于人阅读和编写&#xff0c;同时也易于机器解析和生成。Python内置的json模块提供了简单易用的方法来实现数据的序列化和反序列化。下面将详细介绍如何…...

SpringMVC (1)

目录 1. 什么是Spring Web MVC 1.1 MVC的定义 1.2 什么是Spring MVC 1.3 Spring Boot 1.3.1 创建一个Spring Boot项目 1.3.2 Spring Boot和Spring MVC之间的关系 2. 学习Spring MVC 2.1 SpringBoot 启动类 2.2 建立连接 1. 什么是Spring Web MVC 1.1 MVC的定义 MVC 是…...

Redis 3.2.1在Win10系统上的安装教程

诸神缄默不语-个人CSDN博文目录 这个文件可以跟我要&#xff0c;也可以从官网下载&#xff1a;https://github.com/MicrosoftArchive/redis/releases 这个是微软以前维护的Windows版Redis安装包&#xff0c;如果想要比较新的版本可以从别人维护的项目里下&#xff08;https://…...

springboot医院信管系统

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&a…...

A6.Springboot-LLama3.2服务自动化构建(三)——编写Pipeline构建仓库初始化脚本

下面我们接着上一篇文章《A5.Springboot-LLama3.2服务自动化构建(二)——Jenkins流水线构建配置初始化设置》继续往下分析,编写Pipeline构建脚本。 一、统一Shell执行环境 Jenkins执行Shell脚本时,会在Jenkins节点上创建一个临时的环境来执行该脚本。这个环境包含了Jenki…...

Android 10.0 自定义Window窗口层级新增Type类型功能实现

1.前言 在10.0的系统rom定制化开发过程中,在产品开发过程中,需要新增Window窗口类型来显示 特殊的窗口层级,Window窗口就是根据Type类型来显示的,所以接下来需要新增Type类型来 新增Window窗口显示类型,如图 2.自定义Window窗口层级新增Type类型功能实现的核心类 framew…...

Linux中的基本指令(一)

一、Linux中指令的存在意义 Linux中&#xff0c;通过输入指令来让操作系统执行&#xff0c;以此达到控制操作系统的目的&#xff0c;类似于Windows中的双击&#xff0c;右键新建文件&#xff0c;新建文件夹等 1.补&#xff1a;关于屏幕的几个操作指令 ①清屏指令 clear 回…...

Ruby语言的循环实现

Ruby语言的循环实现深入探讨 在程序设计中&#xff0c;循环是一种常见的控制结构&#xff0c;用于重复执行某些代码块。不同的编程语言提供了不同类型的循环结构&#xff0c;以满足不同的需求。Ruby是一种灵活且易于使用的编程语言&#xff0c;其循环实现方式独具一格&#xf…...

使用docker-compose安装ELK(elasticsearch,logstash,kibana)并简单使用

首先服务器上需要安装docker已经docker-compose&#xff0c;如果没有&#xff0c;可以参考我之前写的文章进行安装。 https://blog.csdn.net/a_lllk/article/details/143382884?spm1001.2014.3001.5502 1.下载并启动elk容器 先创建一个网关&#xff0c;让所有的容器共用此网…...

《Keras 3 在 TPU 上的肺炎分类》

Keras 3 在 TPU 上的肺炎分类 作者&#xff1a;Amy MiHyun Jang创建日期&#xff1a;2020/07/28最后修改时间&#xff1a;2024/02/12描述&#xff1a;TPU 上的医学图像分类。 &#xff08;i&#xff09; 此示例使用 Keras 3 在 Colab 中查看 GitHub 源 简介 设置 本教程将介…...

团体程序设计天梯赛-练习集——L1-012 计算指数

前言 这道题简单至极&#xff0c;几行代码就全都解决了。这次多来几个写法&#xff1b; L1-012 计算指数 真的没骗你&#xff0c;这道才是简单题 —— 对任意给定的不超过 10 的正整数 n&#xff0c;要求你输出 2 的n次方 。不难吧&#xff1f; 输入格式&#xff1a; 输入…...

【机器学习】制造业转型:机器学习如何推动工业 4.0 的深度发展

我的个人主页 我的领域&#xff1a;人工智能篇&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;&#x1f44d;点赞 收藏❤ 引言 在当今科技飞速发展的时代&#xff0c;制造业正经历着前所未有的变革&#xff0c;工业4.0的浪潮席卷而来。工业4.0旨在通过将…...

深度学习篇---数据集分类

文章目录 前言第一部分&#xff1a;VOC数据集标签、COCO数据集格式1.VOC数据集标签的特点及优缺点特点优点缺点 2.COCO数据集标签的特点及优缺点特点优点缺点 3.YOLO数据集标签的特点及优缺点特点优点缺点 第二部分&#xff1a;VOC格式和YOLO格式1.VOC格式3.YOLO格式3.区别(1)文…...

力扣hot100之螺旋矩阵

class Solution:def spiralOrder(self, matrix: List[List[int]]) -> List[int]:# 用四个数对应4个遍历的方向[0, 1, 2, 3] - [右&#xff0c;下&#xff0c;左&#xff0c;上]go_state 0 # 起始必须向右# record_matrix [[0] * n for _ in range(m)]n_0, n_1, n_2, n_3 …...

嵌入式知识点总结 C/C++ 专题提升(一)-关键字

针对于嵌入式软件杂乱的知识点总结起来&#xff0c;提供给读者学习复习对下述内容的强化。 目录 1.C语言宏中"#“和"##"的用法 1.1.(#)字符串化操作符 1.2.(##)符号连接操作符 2.关键字volatile有什么含意?并举出三个不同的例子? 2.1.并行设备的硬件寄存…...

Android 高版本如何获取App安装列表?

有个需求需要获取App内的安装列表,但是现在在高版本Android中,只能获取到一部分App效果,我获取的代码如下: val calendar Calendar.getInstance()val packageManager context.packageManagerval usageStatsManager context.getSystemService(Context.USAGE_STATS_SERVICE) …...

StarGAN:原理、用途及最新发展

一、引言 StarGAN是一种具有广泛应用的生成模型&#xff0c;具有同时生成多种类别数据的能力。它由Yunjey Choi等人在2017年提出&#xff0c;旨在实现图像多域间迁移&#xff0c;尤其适用于人脸属性转换。StarGAN的提出&#xff0c;标志着生成对抗网络&#xff08;Generative A…...

TCP报文格式与核心机制

TCP与UDP都是传输层的重要协议&#xff0c;TCP的特性包括有连接、可靠传输、面向字节流、全双工。 TCP的报文格式如下&#xff1a; 一、报文格式 1.源端口号、目的端口号 源端口和目的端口是五元组中重要的两个性质&#xff0c;源端口即数据是从哪里来的&#xff0c;目的端…...

【2024年华为OD机试】 (B卷,100分)- 金字塔,BOSS的收入(Java JS PythonC/C++)

一、问题描述 微商模式收入计算 题目描述 微商模式中&#xff0c;下级每赚 100 元就要上交 15 元。给定每个级别的收入&#xff0c;求出金字塔尖上的人的收入。 输入描述 第一行输入 N&#xff0c;表示有 N 个代理商上下级关系。接下来输入 N 行&#xff0c;每行三个数&am…...

缓存、数据库双写一致性解决方案

双写一致性问题的核心是确保数据库和缓存之间的数据同步&#xff0c;以避免缓存与数据库数据不同步的问题&#xff0c;尤其是在高并发和异步环境下。本文将探讨双写一致性面临的主要问题和解决方案&#xff0c;重点关注最终一致性。 本文讨论的是最终一致性问题 双写一致性面…...

开放银行数据保护与合规实践案例

总体原则 开放银行的数据处理基本原则指的是数据处理者在数据生命周期的各阶段进行各种数 据处理时均应遵循的根本准则&#xff0c;是指导监管机构制定规范、进行管理以及开放银行进 行具体数据处理行为的纲领。根据《民法典》《个人信息保护法》《数据安全法》 《网络安全法…...

51c自动驾驶~合集47

我自己的原文哦~ https://blog.51cto.com/whaosoft/13083194 #DreamDrive 性能爆拉30%&#xff01;英伟达&#xff1a;时空一致下的生成重建大一统新方案~ 从自车的驾驶轨迹中生成真实的视觉图像是实现自动驾驶模型可扩展训练的关键一步。基于重建的方法从log中生成3D场景…...

2024年AI与大数据技术趋势洞察:跨领域创新与社会变革

目录 引言 技术洞察 1. 大模型技术的创新与开源推动 2. AI Agent 智能体平台技术 3. 多模态技术的兴起:跨领域应用的新风口 4. 强化学习与推荐系统:智能化决策的底层驱动 5. 开源工具与平台的快速发展:赋能技术创新 6. 技术安全与伦理:AI技术的双刃剑 7. 跨领域技…...

【protobuf】二、proto3语法详解①

文章目录 前言Ⅰ. 字段规则Ⅱ. 消息类型的定义和使用1、定义2、使用1️⃣消息类型可作为字段类型使⽤2️⃣可导入其他 .proto 文件的消息并使用 -- import 3、创建通讯录 2.0 版本的 .proto 文件4、通讯录 2.0 版本的读写实现 -- 第一种验证方式5、decode选项 -- 第二种验证方式…...

React 中hooks之useLayoutEffect 用法总结以及与useEffect的区别

React useLayoutEffect 1. useLayoutEffect 基本概念 useLayoutEffect 是 React 的一个 Hook&#xff0c;它的函数签名与 useEffect 完全相同&#xff0c;但它会在所有的 DOM 变更之后同步调用 effect。它可以用来读取 DOM 布局并同步触发重渲染。 2. useLayoutEffect vs us…...

实战经验:使用 Python 的 PyPDF 进行 PDF 操作

文章目录 1. 为什么选择 PyPDF&#xff1f;2. 安装 PyPDF3. PDF 文件的合并与拆分3.1 合并 PDF 文件3.2 拆分 PDF 文件 4. 提取 PDF 文本5. 修改 PDF 元信息6. PDF 加密与解密6.1 加密 PDF6.2 解密 PDF 7. 页面旋转与裁剪7.1 旋转页面7.2 裁剪页面 8. 实战经验总结 PDF 是一种非…...

数据结构与算法之排序: LeetCode 15. 三数之和 (Ts版)

三数之和 https://leetcode.cn/problems/3sum/description/ 描述 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0请你返回所有和为 0 且不重复的三元…...

51c嵌入式~单片机~合集6

我自己的原文哦~ https://blog.51cto.com/whaosoft/13127816 一、STM32单片机的知识点总结 本文将以STM32F10x为例&#xff0c;对标准库开发进行概览。主要分为三块内容&#xff1a; STM32系统结构寄存器通过点灯案例&#xff0c;详解如何基于标准库构建STM32工程 STM3…...

SQL Server Management Studio 表内数据查询与删除指令

查询指令 //select * from 表名称 where 列名称 数据名称 select * from Card_Info where num CC3D4D删除指令&#xff0c;删除数据库有风险&#xff0c;操作不可逆&#xff0c;建议删除前备份&#xff0c;以免删错。 //Delete * from 表名称 where 列名称 数据名称 Delete f…...

Timesheet.js - 轻松打造炫酷时间表

Timesheet.js - 轻松打造炫酷时间表 前言 在现代网页设计中&#xff0c;时间表是一个常见的元素&#xff0c;用于展示项目进度、历史事件、个人经历等信息。 然而&#xff0c;创建一个既美观又功能强大的时间表并非易事。 幸运的是&#xff0c;Timesheet.js 这款神奇的 Java…...

产品经理面试题总结2025【其一】

一、产品理解与定位 1、你如何理解产品经理这个角色&#xff1f; 作为一名互联网产品经理&#xff0c;我理解这个角色的核心在于成为产品愿景的制定者和执行的推动者。具体来说&#xff0c;产品经理是连接市场、用户和技术团队之间的桥梁&#xff0c;负责理解市场需求、用户痛…...

第16章:Python TDD实现多币种货币运算

写在前面 这本书是我们老板推荐过的&#xff0c;我在《价值心法》的推荐书单里也看到了它。用了一段时间 Cursor 软件后&#xff0c;我突然思考&#xff0c;对于测试开发工程师来说&#xff0c;什么才更有价值呢&#xff1f;如何让 AI 工具更好地辅助自己写代码&#xff0c;或许…...

【Web】2025-SUCTF个人wp

目录 SU_blog SU_photogallery SU_POP SU_blog 先是注册功能覆盖admin账号 以admin身份登录&#xff0c;拿到读文件的权限 ./article?filearticles/..././..././..././..././..././..././etc/passwd ./article?filearticles/..././..././..././..././..././..././proc/1…...

C++实现矩阵Matrix类 实现基本运算

本系列文章致力于实现“手搓有限元&#xff0c;干翻Ansys的目标”&#xff0c;基本框架为前端显示使用QT实现交互&#xff0c;后端计算采用Visual Studio C。 目录 Matrix类 1、public function 1.1、构造函数与析构函数 1.2、获取矩阵数值 1.3、设置矩阵 1.4、矩阵转置…...

【GORM】初探gorm模型,字段标签与go案例

GORM是什么&#xff1f; GORM 是一个Go 语言 ORM&#xff08;对象关系映射&#xff09;库&#xff0c;它让我们可以使用结构体来操作数据库&#xff0c;而无需编写SQL 语句 GORM 模型与字段标签详解 在 GORM 中&#xff0c;模型是数据库表的抽象表示&#xff0c;字段标签&am…...

html全局遮罩,通过websocket来实现实时发布公告

1.index.html代码示例 <div id"websocket" style"display:none;position: absolute;color:red;background-color: black;width: 100%;height: 100%;z-index: 100; opacity: 0.9; padding-top: 30%;padding-left: 30%; padding-border:1px; "onclick&q…...

基于VSCode+CMake+debootstrap搭建Ubuntu交叉编译开发环境

基于VSCodeCMakedebootstrap搭建Ubuntu交叉编译开发环境 1 基于debootstrap搭建目标系统环境1.1 安装必要软件包1.2 创建sysroot目录1.3 运行debootstrap1.4 挂载必要的虚拟文件系统1.5 复制 QEMU 静态二进制文件1.6 进入目标系统1.7 使用目标系统&#xff08;以安装zlog为例&a…...

C#中System.Text.Json:从入门到精通的实用指南

一、引言 在当今数字化时代&#xff0c;数据的高效交换与处理成为软件开发的核心环节。JSON&#xff08;JavaScript Object Notation&#xff09;凭借其简洁、轻量且易于读写的特性&#xff0c;已然成为数据交换领域的中流砥柱。无论是前后端数据交互&#xff0c;还是配置文件…...

【深度学习】Huber Loss详解

文章目录 1. Huber Loss 原理详解2. Pytorch 代码详解3.与 MSELoss、MAELoss 区别及各自优缺点3.1 MSELoss 均方误差损失3.2 MAELoss 平均绝对误差损失3.3 Huber Loss 4. 总结4.1 优化平滑4.2 梯度较好4.3 为什么说 MSE 是平滑的 1. Huber Loss 原理详解 Huber Loss 是一种结合…...

Maven下载配置

目录 Win下载配置maven的环境变量 Mac下载安装配置环境变量 MavenSetting.xml文件配置 Win 下载 https://maven.apache.org/ 在主页面点击Download 点击archives 最好不要下载使用新版本&#xff0c;我使用的是maven-3.6.3&#xff0c;我们点击页面下方的archives&#xff0…...

JS基础(5):运算符和语句

一.运算符 1.赋值运算符 加减乘除都是一样的&#xff0c;&#xff0c;-&#xff0c;*&#xff0c;/ 2.一元运算符&#xff1a;经常用来计数 自增&#xff1a; 每次只能加一 自减&#xff1a;-- 前置自增 后置自增 结…...

游戏引擎学习第81天

仓库:https://gitee.com/mrxiao_com/2d_game_2 或许我们应该尝试在地面上添加一些绘图 在这段时间的工作中&#xff0c;讨论了如何改进地面渲染的问题。虽然之前并没有专注于渲染部分&#xff0c;因为当时主要的工作重心不在这里&#xff0c;但在实现过程中&#xff0c;发现地…...

网络安全 | 什么是正向代理和反向代理?

关注&#xff1a;CodingTechWork 引言 在现代网络架构中&#xff0c;代理服务器扮演着重要的角色。它们在客户端和服务器之间充当中介&#xff0c;帮助管理、保护和优化数据流。根据代理的工作方向和用途&#xff0c;代理服务器可分为正向代理和反向代理。本文将深入探讨这两种…...

前缀和——模板 二维前缀和

一.题目描述 【模板】二维前缀和_牛客题霸_牛客网 二.题目解析 这道题和上一道题有点异曲同工之妙。输入一个m行n列的矩阵&#xff0c;然后进行q次操作&#xff0c;每次操作输入4个数&#xff0c;作为两个点的坐标&#xff0c;计算这两个点为对角线的矩阵的和。 三.算法原理 …...

oracle使用case when报错ORA-12704字符集不匹配原因分析及解决方法

问题概述 使用oracle的case when函数时&#xff0c;报错提示ORA-12704字符集不匹配&#xff0c;如下图&#xff0c;接下来分析报错原因并提出解决方法。 样例演示 现在有一个TESTTABLE表&#xff0c;本表包含的字段如下图所示&#xff0c;COL01字段是NVARCHAR2类型&#xff0…...

高等数学学习笔记 ☞ 定积分与积分公式

1. 定积分的基本概念 1.1 定积分的定义 1. 定义&#xff1a;设函数在闭区间上有界。在闭区间上任意插入若干个分点&#xff0c;即&#xff0c; 此时每个小区间的长度记作(不一定是等分的)。然后在每个小区间上任意取&#xff0c;对应的函数值为。 为保证每段的值(即矩形面积)无…...