JavaEE初阶——多线程(线程安全-锁)
复习上节内容(部分-掌握程度不够的)
加锁,解决线程安全问题。
synchronized关键字,对锁对象进行加锁。
锁对象,可以是随便一个Object对象(或者其子类的对象),需要关注的是:是否是对同一个锁对象进行加锁(锁竞争)
进入代码块,加锁;
离开代码块,解锁。
synchronized修饰普通方法,相当于给this加锁(锁对象this);
synchronized修饰静态方法,相当于给类对象加锁
从导致线程安全问题的原因,进行解决。
synchronized(续 上一篇)
synchronized特性。
- synchronized加锁效果具有互斥性。
- 可重入
拿到锁的线程再次对该锁对象进行加锁,不会阻塞;
[ 代码示例 ]
Thread t = new Thread(()->{synchronized(locker){synchronized(locker){System.out.println("hello");}}
});
解释:
(1)上述代码,可以正常打印hello。
(2)原因:
这两次加锁,是在同一个线程进行的。
当前由于是同一个线程,此时锁对象,就知道了第二次加锁的线程,就是持有锁的线程。第二次操作,就可以直接放行通过,不会出现阻塞。 ——可重入(所以这个代码并不会出现锁冲突)
(3)好处:
a.可以避免上述代码出现死锁的情况。(Java中的锁,都是可重入锁。)
如果没有这个特性——比如C++,用的std::mutex锁,就是不可重入的,一旦以上代码出现阻塞,无法自动恢复,所以这个线程就卡死了 ~ ~(这里出现的卡死,就称为“死锁”)
b.其他容易出现这种死锁的情况:
方法/函数的调用关系复杂,加锁的代码比较隐蔽。如下例:
void func1(){加锁func2();解锁;
}void func2(){func3();
}void func3(){func4();
}void func4(){加锁;……解锁;
}
以上示例的代码,直观上看,每个地方都是只加了一次锁。
但是由于复杂的调用关系,就可能导致,加锁重复了。
(4)注意:双重加锁,本身就是代码写的有问题(是有问题的代码逻辑,本来就不应该这样写),所以也没有应用场景 ~ ~
可重入这个特性,就是为了防止咱们在“不小心”中引入问题,就算你不小心了,也没事!!!(即:写错了也能正常运行)
(5)原理:如何能实现可重入性
可重入锁:
内部持有两个信息:
a.当前这个锁是被哪个线程持有的
b.加锁次数计数器
(
初始值为0,加锁一次,+1一次,第一次加锁——也就是为0的时候加锁,会同时记录线程是谁;
判定当前加锁线程是否上持有锁的线程,如果不是同一个线程,阻塞;如果是同一个线程,就只是让计数器++,即可 ~ 没有别的操作了 ~ ~
)
注意:
a.synchronized嵌套多层也可以保证在正确的时机解锁
b.计数器是真正用来识别解锁时机的关键要点 ~ ~
这个源码在JVM中,C++代码实现出来的,在idea中是看不到的
(
【源码】:
Java标准库的源码:这个是通过Java代码写的,idea中都能看到,虽然是.class的,但是idea上你看到的是idea自动帮你反编译的
JVM里的源码:C++写的,在Java层看不到,需要额外下载jvm的源码来看 ~ ~
)
c.最外层的{进行加锁,最外层的}进行解锁
一共只有一把锁(一个锁对象,只有一把锁)
d.锁的加锁次数和线程,不能通过函数进行获取(由JVM封装好了,我们知道就行,不必去干预)
e.(接d.)jconsole可以查看到的是线程的状态,能一定程度上反应出锁的状态,但是并不能获取锁的这两个信息(属性)
PS:【计数器】,这种处理方式,很多地方都会使用到,可以理解为一种处理技巧。
死锁
——多线程代码中的一类经典问题 ~ ~ 也是经典面试题
(加锁是可以解决线程安全问题,但是如果加锁方式不当,就可能产生死锁。)
死锁,属于程序中最严重的一类bug。一旦出现死锁,线程就“卡住了”,无法继续工作。(所以,要想办法避免 ~ ~)
【死锁的三种典型场景】
-
一个线程,一把锁
刚才的代码中,如果是不可重入锁,并且只有一个线程对这把锁加锁两次,就会出现死锁。 -
两个线程,两把锁
线程1 获取到 锁A
线程2 获取到 锁B
接下来,1尝试获取B,2尝试获取A。
就同样出现死锁了!!!举例:
(“互不相让,不懂合作,僵持不前”,执行完run,线程才是结束,这里是僵持住们无法结束了)
运行这个代码,打开jconsole进行查看:
(上边这个例子中,如果约定加锁顺序,先对A加锁,后对B加锁 ~ ~此时,死锁仍然可以解决 ~ ~) -
N个线程M把锁
哲学家就餐问题
(注意,上图中,每个滑稽,都只能拿挨着他的两只筷子)
以上,描述完“哲学家就餐问题”(吃面条——去CPU上运行;思考人生——放下CPU被调度走;拿筷子——加锁)
要想解决死锁问题,就要能够了解原因
↓↓↓
【产生死锁的四个必要条件 ~ ~】
-
互斥使用。(最基本的特性,不太好破坏)
获取锁的过程是互斥的。一个线程拿到了这把锁,另一个线程也想获取,就需要阻塞等待。 -
不可抢占。(锁最基本的特性,不太好破坏)
一个线程拿到了锁之后,只能主动解锁,不能让别的线程强行把锁抢走 ~ ~ -
请求保持。(代码结构,不一定能破坏,要看实际需求 ~有时候代码就是需要两个锁都拿到)
一个线程拿到了锁A之后,在(一直)持有A(没有释放)的前提下,(总是)尝试获取B。 -
循环等待/环路等待(代码结构相关,最容易破坏 ~ ~只需要制定一定的规则,就可以有效的避免循环等待!!!比如:指定加锁顺序 ~ ~)
解决死锁问题,核心思路:破坏上述的必要条件之一,就搞定!!!
【解决死锁】从原因入手(第四条,最容易突破,有很多种方案 ~ ~)
1)引入额外的筷子
2)去掉一个线程
3)引入计数器,限制最多同时多少个人同时吃面
==》1)2)3),这三个方案虽然不复杂,但是,普适性不高,有的时候用不了 ~ ~
4)引入加锁顺序的规则(普适性高,方案容易落地)
5)“银行家算法”
能解决死锁问题,但是这个方案太复杂了!!!理论可行,实践中并不推荐。实际开发中千万不要这么做。先不谈解决死锁问题,很可能你写的银行家算法本身就存在bug。
【问题】“可不可以给‘哲学家’编号,反正每次只能有一位哲学家吃,让他们按编号用餐?”
答:不行。
线程调度的大前提是“随机调度”。
想办法让某个线程 先加锁,违背了“随机调度”根本原则。可行性是不高的。
(而约定加锁顺序,在写代码的层面上,是非常容易做到的 ~ ~)
Java标准库中的线程安全类
标准库有很多 集合类
——这些类,都线程不安全。
多个线程,尝试修改同一个上述的对象,就很容易出现问题!!!
(注意:这里“很容易出现问题”,而不是100%,也可能这个代码写出来后,是没有问题的,具体代码具体分析。多线程的代码,稍微变化一点,就可能有不一样的结果)
这几个类,自带锁了 ~ ~
在多线程环境下的时候,能好点儿 ~ ~
但是,也不是100%不出问题!!只是概率比上面小很多。具体代码,具体分析!!!
(多线程的代码,稍微变化一点,就可能有不一样的结果)
注意:这几个类,都是标准库即将弃用的 ~ ~现在暂时还保留着,未来某一天新版本的jdk可能就把这些内容删了 ~ ~所以,在写新的代码的时候,就尽量别用了,不推荐 ~ ~
拓展:【jdk版本升级】
之前用的一直是jdk8这个经典版本,2014年发行。之后要学到Spring,Spring升级到3之后,不支持jdk8了,最低也需要jdk17.
(另外,Spring升级了,旧版本的Spring虽然仍然能使用,但是修改起来非常麻烦,所以还是建议采用用jdk17这种方案。)
jdk的版本升级虽然快,但是新版本的新东西不算多 ~ ~
【更改方法】
下载安装jdk17,然后把idea设置一下,使用jdk17即可 ~ ~(并不费事,不要退缩!!!)
继续讲解引起线程安全问题的原因
内存可见性
如果一个线程写,一个线程读,也是可能有线程安全问题的。
代码示例:
//这个代码中,预期通过t2线程输入的整数,只要输入的不为0,就可以使t1线程结束。public static int flag = 0;//public 类中的成员变量
public static void main(){Thread t1 = new Thread(()->{while(flag == 0){//循环体里,啥都不写}System.out.println("t1 线程结束!");});Thread t2 = new Thread(()->{System.out.println("请输入 flag 的值:");Scanner sc = new Scanner(System.in);flag = sc.nestInt();});t1.start();t2.start();
}
【预期】通过t2线程输入的整数,只要输入的不为0,就可以使t1线程结束。
【问题】实际输入非0的时候,发现t1并没有真的结束!!!
以上代码出现问题的原因:
(1)JVM对代码做出了优化。
t1的循环体内,什么都没有写,核心指令就只有两条:a.load读取内存中flag的值,到CPU寄存器里。b.拿着寄存器的值和0进行比较(条件跳转指令 ~ ~)
所以,上述循环执行速度就会非常快!!!(a、b两条指令,快速、反复的执行)这样,在这个执行过程中,有两个关键要点:①load操作执行的结果,每次都是一样的!!!(想要输入,也是过几秒才能输入,人并没有那么快。在这几秒之内,已经执行了不知道多少次循环,上百亿次 ~ ~)②load操作,它的开销远远超过条件跳转!!访问寄存器的速度,远远超过访问内存!!频繁执行load和条件跳转,load的开销大,并且load的结果又没有变化(真正出现变是好几秒之后的事:用户输入)。此时,JVM就产生怀疑:这里的load操作是否真的有存在的必要???——JVM就可能做出代码优化 ~ ~JVM把上述load操作,给优化掉!!!(只有前几次执行load,后续发现,load反正都一样,静态分析代码,也没看到哪里改了flag,因此,就直接激进的把load操作,给干掉了)load操作被干掉之后,就相当于不再重复读内存,而直接使用寄存器中之前“缓存”的值 ~ ~大幅地提高了循环的执行速度!!!不过,也因此,导致t2修改了flag的内容,但是t1没有看到这个内存的变化**==》内存可见性问题**
(2)t2修改了内存,但是t1没有看到这个内存的变化(所谓:内存可见性)
以上两条原因,(1)导致了(2),进而导致程序出现了问题。
【拓展:JVM代码优化功能】
(其他)编译器/JVM,都非常厉害。
很多地方都会涉及到代码优化。
确实存在有些程序猿代码写的不太行。因此,设计JVM和编译器的大佬就引入这样的优化能力,在优化的加持下,就能让你即使写不出太高效的代码,最终的执行效率也不会太差 ~ ~ ~
有没有优化,差别非常大。(比如:有服务器,开启优化,10分钟完成启动;关闭优化,30min+)
虽然我们写的只是一份代码,但是编译器和JVM就能只能分析出:当前这份代码哪里不太合理,然后对代码进行调整 ~ ~保证了,在原有逻辑不变的前提下,提高程序效率 ~ ~
很多主流语言的编译器,都有这样的能力(对代码进行不合理分析,调整,逻辑不变,效率提升)
但是!!!原有逻辑不变这点,编译器是没有那么容易正确保持的。(单线程下,还好;多线程下,很容易出现误判——这个可以视作bug)
【对“多线程代码,稍微变化一点,就可能有不一样的结果”的一点例子,帮助理解】
//其实就是对刚才的代码略加改动:在循环体中,加入sleep语句;
Thread t1 = new Thread(()->{while(flag==0){try{Thread.sleep(10);//不加sleep,一秒钟循环上百亿次//load操作的开销非常大,所以优化的迫切程度就更高//加了sleep,一秒钟循环1000次//load整体开销就没那么大了,优化的迫切程度就降低了。//所以可知:编译器什么时候触发优化,不一定。进而,什么时候出现“内存可见性问题”,也就不一定了。(代码稍微改动一点,结果就截然不同。)}catch(InterruptedException e){e.printStackTrace();}}System.out.println("t1线程结束!");
});
解决内存可见性问题【volatile关键字】
——由上述文字可知:需要解决“是否选择启用优化”。
【volatile】强制关闭优化/或称:强制读取内存。
(可以确保示例代码中,每次循环都会重新从内存中读取数据)
这样做,开销是大了,效率是低了,但是数据的准确性、逻辑的正确性,都提高了。
(更多时候,快没有准重要,就加volatile;确实有时候需要快而不要求准,就不加volatile。根据场景需求,作取舍)
这样volatile关键字,就把是否启用优化 的 选择权 ,交给了程序猿自己。
【volatile功能】
-
保证内存可见性(核心功能之一)
/关于 内存可见性,有两种表述/
/(1)前边说过的:
上述代码,编译器发现,每次循环都要读取内存,开销太大。于是就把读取内存操作优化成读取寄存器操作,提高效率。/
/(2)JMM(Java Memory Model)模型(一个抽象的 概念)
上述代码,编译器发现,每次循环都要读取“主内存”,就会把数据从“主内存”中复制到“工作内存”中,后续每次都是读取“工作内存”/
工作内存——不是真正的内存,而是CPU寄存器 或者 CPU的缓存(L1,L2,L3,三级缓存),称为“工作存储区”。
主内存——也就是内存。
、、
引入“工作内存”这个概念,而不直接说“CPU寄存器”,主要是为了“跨平台”。并且不用像说“CPU寄存器或缓存中”这样拗口。 -
禁止指令重排序
注意!!!
只有锁可以完全解决线程安全问题,而 Java 中的锁有两种:synchronized 和 Lock。
volatile 可以解决内存可见性问题,但不能完全解决线程安全问题。
sleep不能解决线程安全问题。
相关文章:
JavaEE初阶——多线程(线程安全-锁)
复习上节内容(部分-掌握程度不够的) 加锁,解决线程安全问题。 synchronized关键字,对锁对象进行加锁。 锁对象,可以是随便一个Object对象(或者其子类的对象),需要关注的是ÿ…...
搭建大语言模型
安装和配置Ollama 首先在官网上下载Ollama,同时支持window,linux,macos系统。 下载下来是一个压缩包,直接解压缩即可,然后点击安装程序开始安装。 linux下载 执行以下命令,即可自动下载安装,…...
QT6 Socket通讯封装(TCP/UDP)
为大家分享一下最近封装的以太网socket通讯接口 效果演示 如图,界面还没优化,后续更新 废话不多说直接上教程 添加库 如果为qmake项目中,在.pro文件添加 QT network QT core gui QT networkgreaterThan(QT_MAJOR_VERS…...
Linux中 vim 常用命令大全详细讲解
文章目录 前言一、Vim 基本操作 🕹️1.1 打开或创建1.2 退出编辑1.3 模式切换 二、Vim 光标移动命令 ↕️2.1 基本移动2.2 行内移动2.3. 单词移动2.4. 页面移动2.5. 行跳转 三、Vim 文本编辑命令 📋3.1 插入和删除3.2 复制、剪切与粘贴3.3 替换与修改 四…...
vs 调试
常用: 调试->窗口-> 断点 监视 自动窗口 局部变量 调用堆栈 内存 反汇编(也可以右键,转到反汇编) 寄存器 快捷键: F5:启用调试,经常用来跳到下一个断点处 F9创建断点和取消断点。断点的重要作用&…...
使用 Kubernetes 部署 Redis 主从及 Sentinel 高可用架构(未做共享存储版)
文章目录 使用 Kubernetes 部署 Redis 主从及 Sentinel 高可用架构Redis 主从架构部署 (1.yaml)Redis Sentinel 部署 (2.yaml)Sentinel 服务暴露 (3.yaml)部署步骤总结 使用 Kubernetes 部署 Redis 主从及 Sentinel 高可用架构 本文将详细介绍如何在 Kubernetes 中部署 Redis …...
PLC网关,plc远程通信 —— 跨越距离远程控制运维升级
在日新月异的工业4.0时代,智能化、网络化已成为制造业转型升级的关键词。其中,PLC(可编程逻辑控制器)作为工业自动化控制的核心设备,其远程通信技术的突破,正引领着一场前所未有的工业变革。今天࿰…...
MySQL的历史和地位
秋招之后,开始深入学习后端开发知识啦。把学到的东西分享给大家最开心啦。就从MySQL开始吧。 首先说一下MySQL的历史和地位。主要是看一下我们为什么要学习,而不是说让我们学什么我们就学什么。 地位 这张图是我从DB-Engines截取的2024年12月最新的数据…...
Day12 洛谷 1320+1152+1615
零基础洛谷刷题记录 Day01 2024.11.18 Day02 2024.11.25 Day03 2024.11.26 Day04 2024.11.28 Day05 2024.11.29 Day06 2024 12.02 Day07 2024.12.03 Day08 2024 12 05 Day09 2024.12.07 Day10 2024.12.09 Day11 2024.12.10 Day12 2024.12.14 文章目录 零基础洛谷刷题记录1320&…...
四十六:如何使用Wireshark解密TLS/SSL报文?
TLS/SSL是保护网络通信的重要协议,其加密机制可以有效地防止敏感信息被窃取。然而,在调试网络应用或分析安全问题时,解密TLS/SSL流量是不可避免的需求。本文将介绍如何使用Wireshark解密TLS/SSL报文。 前提条件 在解密TLS/SSL报文之前&…...
【网络安全设备系列】7、流量监控设备
0x00 定义: 网络流量控制是一种利用软件或硬件方式来实现对电脑网络流量的控制。它的最主要方法,是引入QoS的概念,从通过为不同类型的 网络数据包标记,从而决定数据包通行的优先次序。 0x01 类型: 流控技术分为两种: 一种是…...
SpringCloud无介绍快使用,sentinel注解@SentinelResource的基本使用(二十三)
TOC 问题背景 从零开始学springcloud微服务项目 注意事项: 约定 > 配置 > 编码IDEA版本2021.1这个项目,我分了很多篇章,每篇文章一个操作步骤,目的是显得更简单明了controller调service,service调dao默认安装ngi…...
vue3 父组件调用子组件 el-drawer 抽屉
之前 Vue3 只停留在理论,现在项目重构,刚好可以系统的实战一下,下面是封装了一个抽屉表单组件,直接在父组件中通过调用子组件的方法打开抽屉: 父组件: <template><div id"app"><…...
JVM运行时数据区内部结构
VM内部结构 对于jvm来说他的内部结构主要分成三个部分,分别是类加载阶段,运行时数据区,以及垃圾回收区域,类加载我们放到之后来总结,今天先复习一下类运行区域 首先这个区域主要是分成如下几个部分 下面举个例子来解释…...
luckysheet与superslide冲突解决
[现象]控制台报错、界面无法操作 $是jquery。查看源码,发现mousewheel方法来自插件mousewheel,luckysheet初始应该会将mousewheel挂载在jquery上。 在控制台打印jquery取dom及其方法,结果如下: 不存在mousewheel方法,…...
ubuntu环境调用onnxruntime找不到GPU的问题
问题: python安装好onnxruntime无法调用gpu。 通过如下代码测试,均为False。 import onnxruntime as ort# 检查ONNX Runtime是否支持CUDA def is_onnxruntime_cuda_supported():return ort.get_device() GPU# 检查ONNX Runtime是否使用CUDA def is_onn…...
【iOS】《Effective Objective-C 2.0》阅读笔记(一)
文章目录 前言了解OC语言的起源在类的头文件中尽量少引入其他头文件多用字面量语法,少用与之等价的方法字面量数值字面量数组字面量字典 多用类型常量,少用#define预处理指令用枚举法表示状态、选项、状态码 总结 前言 最近开始阅读一些iOS开发的相关书籍…...
linux在没网的情况下如何校验时间 超详细拿来即用
一、没有校时服务器的话 1、手动修改 sudo date --set"2024-06-17 13:44:00"二、有校时服务器的话 1、手动校时 ntpdate 14.193.73.22、自动校时 写一个校时服务脚本 14.193.73.2 是校验时间服务器 #!/bin/sh while true dontpdate 14.193.73.2sleep 5;hwclock…...
springBoot项目框架创建后缺少iml文件
springBoot项目创建好之后缺少iml文件 解决方案: 按两下ctrl出现一下内容 在右上角project的下拉框中选中缺少文件的项目 输入 mvn idea:module 回车执行重构...
【OJ题解】最长回文子串
个人主页: 起名字真南的CSDN博客 个人专栏: 【数据结构初阶】 📘 基础数据结构【C语言】 💻 C语言编程技巧【C】 🚀 进阶C【OJ题解】 📝 题解精讲 目录 **题目链接****解题思路****1. 初步判断****2. 回文子串性质****3. 判断是…...
kubeadm安装K8s高可用集群之集群初始化及master/node节点加入calico网络插件安装
系列文章目录 1.kubeadm安装K8s高可用集群之基础环境配置 2.kubeadm安装K8s集群之高可用组件keepalivednginx及kubeadm部署 3.kubeadm安装K8s高可用集群之集群初始化及master/node节点加入集群calico网络插件安装 kubeadm安装K8s高可用集群之集群初始化及master/node节点加入ca…...
动态设置路由标题title;动态设置路由配置meta;独享的守卫beforeEnter
案例:同一个页面即使新增,又是编辑、详情页。导致路由配置里的title无法固定 通过路由的独享的守卫beforeEnter解决配置;同时beforeEnter一定程度上可以帮助处理vue3缓存问题 {path: "methodApplicationFormOperate",name: "M…...
探秘UI自动化测试工具Playwright工作原理
相关文章:playwright系列教程 Playwright简介 微软出品的强大工具 Playwright是由微软推出的一款开源自动化测试工具,专门为Web测试和自动化场景而设计。在现代Web开发的快节奏环境下,其凭借出色的性能和丰富的功能,成为众多开…...
111.【C语言】数据结构之二叉树的销毁函数
目录 1.知识回顾 2.分析 3.代码 后序遍历销毁(最简洁) 前序遍历销毁(不推荐) 中序遍历销毁(不推荐) 4.将函数嵌入main函数中执行 1.知识回顾 106.【C语言】数据结构之二叉树的三种递归遍历方式 2.分析 销毁二叉树需要按照一定的顺序去销毁,例如:先销毁根还是先销毁根…...
WPF xaml 文件详解
<div id"content_views" class"htmledit_views"><h2><a name"t0"></a>1.总述</h2> 创建好了WPF项目后,最重要的是对 App和MainWindow的理解,在一开始的时候,极容易就直接在Main…...
win10配置免密ssh登录远程的ubuntu
为了在终端ssh远程和使用VScode远程我的VM上的ubuntu不需要设置密码,需要在win10配置免密ssh登录远程的ubuntu。 在win10打开cmd,执行下面的代码生成密钥对(会提示进行设置,按照默认的配置就行,一直回车)&…...
Android命令行工具--apksigner
使用 Android SDK Build Tools 修订版 24.0.3 及更高版本中提供的 apksigner 工具为 APK 签名,并确保 APK 的签名将在该 APK 支持的所有版本 Android 平台上成功通过验证。 注意:如果在使用 apksigner 为 APK 签名后又对 APK 做了更改,则 APK…...
Linux高性能服务器编程 | 读书笔记 |9.定时器
9. 定时器 网络程序需要处理定时事件,如定期检测一个客户连接的活动状态。服务器程序通常管理着众多定时事件,有效地组织这些定时事件,使其在预期的时间被触发且不影响服务器的主要逻辑,对于服务器的性能有至关重要的影响。为此&…...
UE5制作伤害浮动数字
效果演示: 首先创建一个控件UI 添加画布和文本 文本设置样式 添加伤害浮动动画,根据自己喜好调整,我设置了缩放和不透明度 添加绑定 转到事件图表,事件构造设置动画 创建actor蓝图类 添加widget 获取位置 设置位移 创建一个被击中…...
双亲委派机制是Java类加载器的一种工作模式
双亲委派机制是Java类加载器的一种工作模式,确保了类加载的一致性和安全性。以下是对双亲委派机制的详细解析: 一、定义与工作原理 双亲委派机制(Parent Delegation Model)要求除了顶层的启动类加载器外,其余的类加载…...
AI智算-k8s部署大语言模型管理工具Ollama
文章目录 简介k8s部署OllamaOpen WebUI访问Open-WebUI 简介 Github:https://github.com/ollama/ollama 官网:https://ollama.com/ API:https://github.com/ollama/ollama/blob/main/docs/api.md Ollama 是一个基于 Go 语言开发的可以本地运…...
百度23届秋招研发岗A卷
百度23届秋招研发岗A卷 2024/12/16 1.下面关于 SparkSQL 中 Catalyst 优化器的说法正确的是(ABC) A.Catalyst 优化器利用高级编程语言功能(例如 Scala 的模式匹配)来构建可扩展的查询优化器 B.Catalyst 包含树和操作树的规则集…...
米哈游大数据面试题及参考答案
怎么判断两个链表是否相交?怎么优化? 判断两个链表是否相交可以采用多种方法。 一种方法是使用双指针。首先分别遍历两个链表,得到两个链表的长度。然后让长链表的指针先走两个链表长度差的步数。之后,同时移动两个链表的指针,每次比较两个指针是否指向相同的节点。如果指…...
Android14 AOSP 允许system分区和vendor分区应用进行AIDL通信
在Android14上,出于种种原因,system分区的应用无法和vendor分区的应用直接通过AIDL的方法进行通信,但是项目的某个功能又需要如此。 好在Binder底层其实是支持的,只是在上层进行了屏蔽。 修改 frameworks/native/libs/binder/Bp…...
llm chat场景下的数据同步
背景 正常的chat/im通常是有单点登录或者利用类似广播的机制做多设备间内容同步的。而且由于长连接的存在,数据同步(想起来)相对简单。而llm的chat在缺失这两个机制的情况下,没见到特别好的做到了数据同步的产品。 llm chat主要两…...
视频去重原理及 Demo 示例
视频去重是一个常见的需求,主要用于视频库或平台管理中,通过判断视频是否相同(或相似)来移除冗余内容。实现视频去重可以通过多种方法,具体选择取决于业务场景和性能要求。 1. 视频去重的原理 1.1 基本原理 视频去重…...
【GIS教程】使用GDAL-Python将tif转为COG并在ArcGIS Js前端加载-附完整代码
目录 一、数据格式 二、COG特点 三、使用GDAL生成COG格式的数据 四、使用ArcGIS Maps SDK for JavaScript加载COG格式数据 一、数据格式 COG(Cloud optimized GeoTIFF)是一种GeoTiff格式的数据。托管在 HTTP 文件服务器上,可以代替geose…...
【ETCD】【源码阅读】深入解析 EtcdServer.applySnapshot方法
今天我们来一步步分析ETCD中applySnapshot函数 一、函数完整代码 函数的完整代码如下: func (s *EtcdServer) applySnapshot(ep *etcdProgress, apply *apply) {if raft.IsEmptySnap(apply.snapshot) {return}applySnapshotInProgress.Inc()lg : s.Logger()lg.In…...
C# 实现 10 位纯数字随机数
本文将介绍如何用 C# 实现一个生成 10 位纯数字随机数的功能。以下是完整的代码示例: using System; using System.Collections.Generic; using System.Linq; using System.Text;namespace RandomTset {class Program{// 使用GUID作为种子来创建随机数生成器static…...
【热力学与工程流体力学】流体静力学实验,雷诺实验,沿程阻力实验,丘里流量计流量系数测定,局部阻力系数的测定,稳态平板法测定材料的导热系数λ
关注作者了解更多 我的其他CSDN专栏 过程控制系统 工程测试技术 虚拟仪器技术 可编程控制器 工业现场总线 数字图像处理 智能控制 传感器技术 嵌入式系统 复变函数与积分变换 单片机原理 线性代数 大学物理 热工与工程流体力学 数字信号处理 光电融合集成电路…...
黑盒白盒测试
任务1 黑盒测试之等价类划分法 【任务需求】 【问题】例:某报表处理系统要求用户输入处理报表的日期,日期限制在2003年1月至2008年12月,即系统只能对该段期间内的报表进行处理,如日期不在此范围内,则显示输入错误信息…...
D99【python 接口自动化学习】- pytest进阶之fixture用法
day99 pytest使用conftest管理fixture 学习日期:20241216 学习目标:pytest基础用法 -- pytest使用conftest管理fixture 学习笔记: fixture(scope"function") conftest.py为固定写法,不可修改名字,使用c…...
RFDiffusion 计算二面角函数解读
th_dih函数来自util.py包,get_dih函数来自kinematics.py包。th_dih函数计算输入向量定义的二面角的余弦值和正弦值,返回一个包含 (cos(ϕ),sin(ϕ)) 的张量。get_dih 函数计算的是传统意义上的二面角。 源代码: def th_dih_v(ab, bc, cd):def th_cross(a, b):a, b = t…...
卓易通:鸿蒙Next系统的蜜糖还是毒药?
哈喽,我是老刘 最近很多人都在问鸿蒙next系统新上线的卓易通和出境易两款应用。 老刘分析了一下这个软件的一些细节,觉得还是蛮有意思的,我觉得可以从使用体验、底层原理和对鸿蒙生态的影响这三个角度来分析一下。 使用体验 性能 看到了一些测…...
Android:展锐T760平台camera PDAF调试
一、平台PDAF流程 目前展锐平台主要支持Shield PD Sensor、Dual PD Sensor 1、Shield PD Sensor Type1相位差和信心度结果直接从Sensor输出,不经过平台算法库。 Type2Sensor端抽取PD信息, 放在一块buffer输出, PDAF算法库算出相位差和信心度。 Type3Sensor端直接输出将带有…...
泷羽Sec学习笔记-zmap搭建炮台
zmap搭建炮台 zmap扫描环境:kali-linux 先更新软件库 sudo apt update 下载zmap sudo apt install zmap 开始扫描(需要root权限) sudo zmap -p 80 -o raw_ips.txt 代码解析: sudo:以超级用户(管理员)权限运行…...
web遇到的安全漏洞
最近项目又在做安全漏扫,记录下遇到的常见的web安全问题 越权 漏洞介绍 攻击者可以在授权状态下,通过修改数据包的参数,操作超出现有权限操作的功能点。举例 修改密码时,可以通过修改名称参数,修改任意用户密码。 任…...
Starfish 因子开发管理平台快速上手:如何完成策略编写与回测
DolphinDB 开发的因子开发管理平台 Starfish 围绕量化投研的因子、策略开发阶段设计,为用户提供了一个从数据管理、因子研究到策略回测的完整解决方案。 因子平台的回测引擎提供了多个关键的事件函数,涵盖策略初始化、每日盘前和盘后回调、逐笔、快照和…...
Oracle 数据库中,UNION ALL创建视图的使用详解
目录 UNION ALL 的特点 UNION ALL 的作用 1. 合并结果集 2. 保留重复行 3. 提高性能 UNION ALL 的使用场景 1. 日志或数据拼接 2. 区分数据来源 3. 解决分区表查询 注意事项 在创建视图中的作用 场景 1:合并多个表的数据到视图 表结构 目标 SQL 实现…...
无名信号量和条件变量
1.使用无名信号量实现春夏秋冬的输出 #include <myhead.h> sem_t sem1,sem2,sem3,sem4; void *fun1() {while(1){sem_wait(&sem1);sleep(1);printf("春\n");sem_post(&sem2);} } void *fun2() {while(1){sem_wait(&sem2);sleep(1);printf("夏…...