【多线程5】面试常考锁知识点
文章目录
- 悲观/乐观锁
- 挂起等待锁/自旋锁
- 偏向锁
- 轻量级/重量级锁
- 锁升级
- CAS
- CAS引发的ABA问题
- 解决方案
- 原子类
- 公平/不公平锁
- 可重入锁
- ReentrantLock
- 读写锁
- Callable接口
这里的“悲观”“乐观”“挂起等待”“自旋”“轻量级”“重量级”“公平”“非公平”“可重入”仅代表某个锁的特性,不具体指某个锁。
悲观/乐观锁
悲观锁:总是在考虑最坏的情况,认为在拿数据时总是存在线程不安全问题,总是认为别人在同时修改这个数据,于是每次拿的时候给这个数据上锁,让其他线程拿不了直到锁释放。代表有synchronized、ReentrantLock。(重量级锁有悲观锁的影子!)
乐观:总是考虑最好的情况,认为总是不存在有线程在同时修改的情况,放心的去拿数据,但是乐观锁有CAS的机制,如果要进行更新操作,发现读取到更新之间有其他线程修改了这个数据,则会放弃修改,重新读取再修改直到成功。代表有原子类,原子类底层就是不断的CAS。(轻量级锁、偏向锁都有乐观锁的影子!)
挂起等待锁/自旋锁
自旋锁:线程未获得锁则不断尝试获取锁。可以及时获得锁,CPU空转(忙等),但缺点是可能会很消耗CPU资源,因此自旋到一定条件(设定时间、次数)就不自旋了。
while(抢锁失败){ 抢;if(!自旋条件) break;
}
挂起等待锁:线程未获得锁则进入阻塞状态,等待被唤醒。不会很消耗CPU资源,但缺点是等待周期可能会很长,不能及时获得锁。
偏向锁
当同步代码块只有一个线程运行时(可以理解为只有一个线程参与锁竞争),此时并不会给这个线程加锁,而是给这个线程一个标记ID(由JVM记录,这个机制也实现了Java的可重入锁,方便理解可参考我写的解决死锁段落),当下一次进入同步代码块时,根据这个ID判断是不是仍然还是这个线程,如果是则直接运行,否则偏向锁升级为轻量级锁,锁持有者为获取锁的线程,其他线程自旋。
上面的过程有点抽象,总结来说:只有一个线程执行同步代码块的时候,此刻加的锁为偏向锁,如果发生其他线程(同时竞争不激烈)来竞争锁,则锁升级为轻量级锁,如果竞争再激烈,则升级为重量级锁。
轻量级/重量级锁
轻量级锁:锁竞争不激烈的场景下,线程未获得锁则保持自旋(不阻塞等待一直尝试获取锁)。
重量级锁:锁竞争激烈的场景下,线程未竞到锁则进入阻塞状态,等待被唤醒,典型:synchronized
锁升级
Java的synchronized有锁升级的机制:
synchronized自适应进行升级的过程,保证了JVM不盲目加锁浪费资源,在锁竞争缓和的情况下线程不阻塞浪费时间,及时获取到锁,在锁竞争激烈的情况下,让线程阻塞减轻CPU负担。
CAS
CAS(Compare And Swap)。顾名思义先比较再交换,CAS涉及到三个数据,这里可以理解为value(修改前读取到的值;主内存中的共享变量)、exceptValue(上一次修改后保存的值;线程里的局部变量)、swapValue(要修改的值;线程里的局部变量)。定义为exceptValue是因为CAS期待exceptValue修改为swapValue。
CAS的工作机制:
- 读取内存值(value)。
- 比较 value 和exceptValue。
- 如果相等,则写入 swapValue,否则CAS失败。
这三步操作是不可分割的也就是说一次CAS是原子性的。
exceptValue的值在CAS成功后被更新为value,否则保持原值不变。
CAS引发的ABA问题
假设原值为A,要修改为B。如果存在多个线程要执行这个修改操作:
- 一个线程修改成功后,由于缓存一致性协议,value变化时,其他线程已经读取的value也会被强制刷新为最新值。多个线程进行CAS(A,A,B)时,一个成功后,其他的线程会CAS失败,不会对A重复CAS(A,A,B)。
- 但是CAS只检查值,不关心在修改这个值之前是否发生了A->B->…->A这种骚操作。由此引发了ABA问题。例如:
线程t1要将A修改为B,而线程t2要将A修改为B,再修改为A;
如果t2先执行完这两个CAS操作,t1由于缓存一致性协议会实时读取到最新值,所以t1在CAS前里面的A变为B再变为A,t1执行CAS,两次线程结束后最终结果为B。
虽然上面这ABA操作看起来没问题,但极端情况下却容易出问题:
我有200块存款,要取100块钱;
我来到ATM,插卡输密码,设置取100块再点击确定,恰好系统超时没有及时吐钱,我恼怒的再摁了一下,由此产生了两个线程t1,t2。两个线程都要CAS(200,200,100),正常情况下,总有一个成功而另一个失败,但是又恰好老妈打给我100块生活费,产生线程t3,在t2完成CAS后,t3又来一波CAS(100,100,200)加了100块,没有t3,t1应该是CAS(100,200,100)但现在成了CAS(200,200,100),于是ATM再吐100块。
这是不符合实际的,现实生活即便手痒快速摁几下,也不会重复响应。
解决方案
为此基于CAS只比较新旧值的特性引入了版本号,版本号是一个单调递增的常量,每次CAS就+1,这样即便A->B->A也能因为版本号而察觉到。
原子类
针对多线程操作共享变量例如例如变量自增这种而不发生线程不安全问题,可以使用原子类。原子类底层使用了CAS,可以保证变量操作的原子性,常见的原子类有AtomicInteger、AtomicIntegerArray、AtomicBoolean、AtomicLong、AtomicReference、AtomicStampedReference。举例AtomicInteger:
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;public class Main {public static void main(String[] args) {AtomicInteger i = new AtomicInteger();i.addAndGet(1); //对于int/Integer i,相当于i+=1System.out.println(i);i.decrementAndGet();//相当于--iSystem.out.println(i);i.getAndDecrement();//相当于i--System.out.println(i);i.incrementAndGet();//相当于++iSystem.out.println(i);i.getAndIncrement();//相当于i++System.out.println(i);}
}
公平/不公平锁
Java对公平锁的定义是先来后到,哪个线程先抢锁就哪个线程拿锁,所以非公平锁就是所有锁竞争者获得锁的机会均等(操作系统随机调度线程)。
可重入锁
一个线程执行到同步代码块给自己加了锁,在这个代码块里又给自己加了锁,造成了死锁,这个线程就自己阻塞自己,锁也释放不了。如果允许线程给自己多次加锁,但又不会发生死锁,同步代码块执行完后锁正常释放,那就是可重入锁。
学Java的同学不用担心死锁的问题,只要以Reentrant开头命名的锁都是可重入锁,而且JDK提供的所有现成的Lock实现类,包括synchronized关键字锁都是可重入的。
ReentrantLock
和synchronized同级别,是在Java5以后引入的,相比于synchronized对锁的使用更灵活,也更复杂。以下是同synchronized的对比:
synchronized | ReentrantLock | |
---|---|---|
实现方式 | synchronzied是关键字,实现机制在JVM内部,需要手动解锁 | ReentrantLock是Java.util.concurrent.locks.ReentrantLock里的类,是在JVM外部实现的,而ReentrantLock需要手动unlock()解锁 |
锁竞争处理 | 线程锁竞争失败会一直阻塞 | 不会阻塞;可以通过trylock(TIME)/trylock()返回一个boolean值,如果是false代表竞争锁失败,调用者可根据这个判断编写竞争失败的代码逻辑 |
锁特性 | 非公平锁 | 默认非公平锁,可通过构造方法传入ture成为公平锁 |
等待和唤醒 | 可通过Object类的wait()、notify()进行等待和唤醒,但唤醒目标是随机的 | 可通过Condition类指定唤醒某个线程 |
常用方法lock()、trylock(Time)、unclock()。
import java.util.concurrent.locks.ReentrantLock;public class Main {public static void main(String[] args) {ReentrantLock locker=new ReentrantLock();Thread t1=new Thread(()->{for(int i=0; i<500; i++){try{locker.lock();System.out.println(Thread .currentThread().getName()+i);}finally{locker.unlock();//未防止忘记释放锁,将其放在finally里}}});t1.start();}
}
读写锁
多个线程对共享变量的读取是不会发生线程不安全的的,如果有写入的情况才会发生:
- 所有线程只读,线程安全
- 所有线程写入,线程不安全
- 有读有写,线程不安全
当有多个线程操作一个共享变量时,对其加锁且对它的读取是不互斥,但是写入时只能一个线程持有锁,达到:
- 读与读之间不互斥
- 所有线程写入,一个线程持有锁其他阻塞
- 有读有写,一个线程持有锁其他阻塞
于是我们引入了读写锁ReentrantReadWriteLock类,通过ReentrantReadWriteLock.readLock获取一个读锁ReadLock对象;通过ReentrantReadWriteLock.writeLock获取一个写锁WriteLock对象。
这两个对象使用lock()、tryLock()、**unlock()**来加锁释放锁。
import java.util.concurrent.locks.ReentrantReadWriteLock;public class Main {static int i=0;public static void main(String[] args) {ReentrantReadWriteLock locker=new ReentrantReadWriteLock();Thread t1=new Thread(()->{locker.readLock().lock();//readLock是ReentrantReadWriteLock类里RreadLock类型的字段System.out.println(i);locker.readLock().unlock();locker.writeLock().lock();//writeLock是ReentrantReadWriteLock类里WriteLock类型的字段i+=1;locker.writeLock().unlock();});t1.start();}
}
Callable接口
Callable类似于Runnable接口,里面定义了call()方法,同run()方法一样对任务进行了包装。
但不同的是Callable接口带有泛型,且call()方法带有返回值,且不可直接将实现了Callable接口的类对象作为参数直接传入Thread类的构造方法里,需要通过FutureTask类将任务提交到线程里。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class Main {public static void main(String[] args) throws InterruptedException, ExecutionException {//返回一个实现了Callable接口的匿名类对象Callable<Integer> callable = (() -> {int sum = 0;for (int i = 1; i <= 100; i++) {sum += i;}return sum;});FutureTask<Integer> futureTask = new FutureTask<>(callable);//FutureTask实现了RunnableFuture接口,RunnableFuture继承了Runnable接口Thread t = new Thread(futureTask);t.start();System.out.println(futureTask.get());}
}
如果要实现上面同样的功能,还需在Main里定义一个static字段类记录sum的值方便任务执行完后来确定任务效果。而通过call()带返回值的属性和new FutureTask.get()方法得到任务结果,将任务和线程分开,达到高内聚低耦合的目的。
完。
相关文章:
【多线程5】面试常考锁知识点
文章目录 悲观/乐观锁挂起等待锁/自旋锁偏向锁轻量级/重量级锁锁升级CASCAS引发的ABA问题解决方案 原子类 公平/不公平锁可重入锁ReentrantLock读写锁 Callable接口 这里的“悲观”“乐观”“挂起等待”“自旋”“轻量级”“重量级”“公平”“非公平”“可重入”仅代表某个锁的…...
Linux第一个系统程序——进度条
1.回车与换行 回车(CR, \r): 作用:将光标移动到当前行的行首(最左侧),但不换到下一行。 历史来源:源自打字机的“回车”操作——打字机的滑架(Carriage)需…...
C 语 言 --- 指 针 3
C 语 言 --- 指 针 3 函 数 指 针函 数 指 针 数 组代 码 解 释回 调 函 数 - - - qsort模 拟 实 现 qsort 函 数 总结 💻作 者 简 介:曾 与 你 一 样 迷 茫,现 以 经 验 助 你 入 门 C 语 言 💡个 人 主 页:笑口常开x…...
蓝桥杯之递归
1.数字三角形 题目描述 上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和(路径上的每一步只可沿左斜线向下或右斜线向下走)。 输…...
学习笔记十八——Rust 封装
🧱 Rust 封装终极指南:结构体、模块、Trait、目录结构与模块引用 🧭 目录导航 什么是封装?Rust 的封装理念Rust 的封装工具总览模块(mod)和访问控制(pub)详解结构体和枚举ÿ…...
【面试向】点积与注意力机制,逐步编码理解自注意力机制
点积(dot product)两个向量点积的数学公式点积(dot product)与 Attention 注意力机制(Attention)注意力机制的核心思想注意力机制中的缩放点积自注意力机制中,谁注意谁? 逐步编码理解…...
基础数学知识-线性代数
1. 矩阵相乘 c i j = a i k ∗ b k j c_{ij} = a_{ik} * b_{kj} cij=aik∗bkj 1. 范数 1. 向量的范数 任意一组向量设为 x ⃗ = ( x 1 , x 2 , . . . , x N ) \vec{x}=(x_1,x_2,...,x_N) x =(x1,x2,...,xN) 如下: 向量的1范数: 向量的各个元素的绝对值之和∥ …...
【KWDB 创作者计划】_上位机知识篇---Docker容器
文章目录 前言1. Docker 容器是什么?隔离性轻量级可移植性可复用性 2. Docker 核心概念镜像容器仓库Dockerfile 3. Docker 基本使用(1) 安装 Docker(2) 容器生命周期管理(3) 镜像管理(4) 进入容器内部(5) 数据持久化(挂载卷)(6) 网络管理 4. …...
指针函数和函数指针
指针函数本质是一个函数,只是函数的返回值是指针类型 函数指针本质是一个指针,只是这个指针指向的是一个函数 指针函数 函数有很多类型的返回值,例如 short funcA(参数列表) // 表示该函数返回值是一个short类型 void funcA(参数列表) // 表…...
案例驱动的 IT 团队管理:创新与突破之路:第六章 组织进化:从案例沉淀到管理体系-6.1 案例库建设方法论-6.1.2案例分级与标签体系
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 案例分级与标签体系构建方法论:IT团队知识管理的结构化实践1. 案例库建设的战略价值与核心挑战1.1 案例管理的战略定位1.2 分级标签体系的核心价值 2. 案例分级体…...
sqlilabs-Less之HTTP头部参数的注入——基础篇
Less-18 user-agent报错注入 这一关的代码漏洞点出现在了insert语句,因为这里没有对user-agent和ip_address进行过滤,,并且输出了mysql的错误信息 补充知识点 PHP里用来获取客户端IP的变量 $_SERVER[HTTP_CLIENT_IP] #这个很少使用…...
java多线程相关内容
java线程创建的方式 一共有四种方式 继承 Thread 类:本质上是实现了 Runnable 接口的一个实例,代表一个线程的实例 启动线程的唯一方 法就是通过 **Thread 类的 start()**实例方法。start()方法是一个 native 方法,它将启动一个新线 程&…...
Windows Server .NET Core 应用程序部署到 IIS 解决首次访问加载慢的问题
第一篇: Windows .NET Core 应用程序部署到 IIS 解决首次访问加载慢的问题 第二篇:Windows Server .NET Core 应用程序部署到 IIS 解决首次访问加载慢的问题 第三篇:Windows .NET Core 应用程序部署到 IIS 解决首次访问加载慢的问题 设置…...
ubuntu24.04上使用qemu+buildroot+uboot+linux+tftp+nfs模拟搭建vexpress-ca9嵌入式linux开发环境
1 准备工作 1.1 安装依赖工具 sudo apt-get update && sudo apt-get install build-essential git bc flex libncurses5-dev libssl-dev device-tree-compiler1.2 安装arm交叉编译工具链 sudo apt install gcc-arm-linux-gnueabihf安装之后,在终端输入ar…...
Cocos Creater打包安卓App添加隐私弹窗详细步骤+常见问题处理
最终演示效果,包含所有代码内容 + 常见错误问题处理 点击服务协议、隐私政策,跳转到相关网页, 点击同意进入游戏,不同意关闭应用 一,添加Activity,命名为MyLaunchActivity 二,编写MyLaunchActivity.java的内容 package com.cocos.game.launch;import android.os.Bund…...
UI文件上传
1、文件上传:文件上传是自动化中比较麻烦棘手的部分。 有些场景我们需要上传本地文件到项目里。这种比较麻烦,因为需要点开文件上传的窗口后,打开的是windows的文件选择窗口, 而selenium是无法操作这个窗口的。 selenium只能操作…...
2.凸包优化求解
1.减而治之(Decrease and Conquer) 插入排序 典型的减而治之算法就是插入排序方法 插入排序法: 在未排序中选择一个元素,插入到已经排序号的序列中 将凸包也采用减而治之的方法 2.In-Convex-Polygon Test 怎么判断引入的极点存在于多边形里面还是外面࿱…...
从0开发一个unibest+vue3项目,使用vscode编辑器开发,总结vue2升vue3项目开始,小白前期遇到的问题
开头运行可看官网 链接: unibest官网 一:vscode中vue3代码显示报错标红波浪线 去查看扩展商店发现一些插件都弃用了,例如h5的插件以及vue老插件 解决办法:下载Vue - Official插件(注意:横杠两边是要加空格的ÿ…...
jmeter中文乱码问题解决
修改jmeter.properties配置文件 进入JMeter安装目录的bin文件夹,找到jmeter.properties文件。搜索参数sampleresult.default.encodingUTF-8,取消注释(删除行首的#),并将其值改为UTF-8。保存文件并重启JMeter生效…...
额外篇 非递归之美:归并排序与快速排序的创新实现
个人主页:strive-debug 快速排序非递归版本 非递归版本的快速排序是为了解决在空间不够的情况下,利用栈来模拟递归的过程。 递归版本的快速排序是空间换时间,好实现。 实现思路: 1. 创建一个栈,将数组的右边界下标和…...
[文献阅读] EnCodec - High Fidelity Neural Audio Compression
[文献信息]:[2210.13438] High Fidelity Neural Audio Compression facebook团队提出的一个用于高质量音频高效压缩的模型,称为EnCodec。Encodec是VALL-E的重要前置工作,正是Encodec的压缩量化使得VALL-E能够出现,把语音领域带向大…...
JavaSpring 中使用 Redis
创建项目 配置 Redis 服务地址 创建 Controller 类 由于当前只是些简单的测试代码,所以就不进行分层了,只创建一个 Controller 来实现 jedis 通过 jedis 对象里的各种方法来操作 Redis 此处通过 StringRedisTemplate 来操作 Redis 最原始提供的类是 Re…...
B端可视化像企业数据的透视镜,看清关键信息
在数字化时代,数据已成为企业最宝贵的资产之一。然而,数据的价值不仅取决于其数量,更在于企业能否快速、准确地提取关键信息并据此做出决策。B端可视化技术的出现,为企业提供了一种强大的工具,它如同企业的“透视镜”&…...
【愚公系列】《Python网络爬虫从入门到精通》055-Scrapy_Redis分布式爬虫(安装Redis数据库)
🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! …...
【MySQL】SQL语句在MySQL中的执行过程?主要存储引擎区别?
MySQL SQL语句执行过程详解 作为面试官,我来详细剖析一条SQL语句在MySQL中的完整执行过程,这是每个后端开发者都应该掌握的核心知识。 一、连接阶段 建立连接 客户端通过TCP/IP协议与MySQL服务器建立连接(默认3306端口)服务器验证用户名、密码和权限…...
致远OA——数据回填表单
文章目录 :apple: 业务需求描述:pineapple: 业务分析和实现 🍎 业务需求描述 测试案例: https://pan.quark.cn/s/3f58972f0a27 官网地址: https://open.seeyoncloud.com/v5devCAP/94/355/359/399/405/406.html 需求描述: 点…...
MongoDB导出和导入数据
安装mongodump工具 参考文章mongodump工具安装及使用详解_mongodump安装-CSDN博客 MongoDB导入导出和备份的命令工具从4.4版本开始不再自动跟随数据库一起安装,而是需要自己手动安装。 官方网站下载链接:Download MongoDB Command Line Database Tools …...
蓝桥杯之递归二
1.数的划分 题目描述 将整数 nn 分成 kk 份,且每份不能为空,任意两份不能相同(不考虑顺序)。 例如:n7,k3n7,k3,下面三种分法被认为是相同的。 1,1,5;1,5,…...
【大疆dji】ESDK开发环境搭建(软件准备篇)
接上一篇【大疆dji】ESDK开发环境搭建(硬件准备篇) 1. 编译环境 ESDK 提供 x86_64/aarch64 基于 Linux 平台 Ubuntu 发行版操作系统构建的静态库,运行 demo 先正确安装所需的依赖包。arm32位就不支持了。建议使用编译安装的方式,…...
Android TTY设备调用流程和简单分析
Linux TTY系统中ioctl的调用流程详解:从应用层到MSM GENI Serial驱动 本文档详细分析Linux系统中从用户空间应用程序发起TTY ioctl请求到特定驱动(例如msm_geni_serial_ioctl)的完整调用流程,包括32位应用与64位内核之间的兼容性问题分析。 1. 总体调用路径概览 以下是完…...
数字孪生赋能管理系统,降本增效立竿见影
1. 数字孪生基础概念及其在管理系统中的应用前景 数字孪生是一种集成多学科、多物理量、多尺度、多概率的仿真过程,在虚拟空间中完成映射,从而反映相对应的实体装备的全生命周期过程。其核心在于将现实世界中的物理对象或系统与其数字化模型相结合&…...
Java学习手册:Web 应用架构概述
一、Web 应用架构的演变 在互联网发展的初期阶段,Web 应用普遍采用客户端 / 服务器(C/S)架构模式。客户端应用程序与服务器端应用程序直接建立连接,进行数据交互和业务处理。然而,这种架构存在诸多局限性。由于客户端…...
企业网站安装 SSL安装的必要性
能够带来安全的加密和快速的访问体验,防止中间人的流量劫持,保障用户隐私信息的安全,帮助用户识别钓鱼网站,提升网站在搜索引擎的排名。 能够防止黑客盗走客户银行卡账号的机密信息,保证信息的机密性,防止…...
【CF】Day38——Codeforces Round 965 (Div. 2) B
B. Minimize Equal Sum Subarrays 题目: 思路: 直觉题 我们可以这样构造,将整个数列左移一位即可,为什么呢? 因为这样我们能尽可能地保证数列的数字尽可能多的同时 且 有一个数不同 这里介绍一个rorate函数…...
leetcode 300. Longest Increasing Subsequence
目录 题目描述 第一步,明确并理解dp数组及下标的含义 第二步,分析明确并理解递推公式 第三步,理解dp数组如何初始化 第四步,理解遍历顺序 代码 题目描述 这是动态规划解决子序列问题的例子。 第一步,明确并理解…...
解密大模型背后的秘密:训练、优化与挑战
解密大模型背后的秘密:训练、优化与挑战 在当今的人工智能领域,大模型(Large Language Models, LLMs)已经成为了一个不可忽视的存在。从自然语言处理到图像生成,再到推荐系统,大模型以其强大的泛化能力和创…...
第33讲|遥感大模型在地学分类中的初探与实战
目录 🧠 一、什么是“遥感大模型”? 📚 二、遥感大模型在地学分类中的优势 📍三、案例:使用 Segment Anything Model (SAM) 进行遥感地物分割 📦 1. 安装与依赖配置(PyTorch) 🖼 2. 读取遥感图像(可用 Sentinel-2 伪彩色图) 🔧 3. SAM 模型载入 💡 …...
LeetCode 438 找到字符串中所有字母异位词
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。 示例 1: 输入: s "cbaebabacd", p "abc" 输出: [0,6] 解释: 起始索引等于 0 的子串是 "cba", 它是 "…...
【25软考网工笔记】第二章(6)脉冲编码调制PCM、通信和交换方式
目录 一、脉冲编码调制PCM 1. 脉冲编码调制的数字化过程 1)采样 2)量化 3)编码 2. PCM计算 3. 应用案例 1)例题1 2)例题1 3)例题3 知识小结 二、通信和交换方式 1.数据通信方式分类 1&#x…...
JSON学习笔记
文章目录 1. JSON是什么2. JSON的特点与结构3. JSON的使用4. JSON文件读取 1. JSON是什么 JSON(JavaScript Object Notation,JavaScript对象表示法)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和…...
高阶指南:动态定价下eBay利润率控制的4维财务模型
在eBay平台上,动态定价(Dynamic Pricing)早已不是新鲜概念。随着市场供需的瞬时波动、竞争产品的变化,以及跨境电商红海局势的加剧,卖家若想在残酷的价格战中保住利润、稳住运营基本盘,仅靠经验主义已经远远…...
【NLP 66、实践 ⑰ 基于Agent + Prompt Engineering文章阅读】
你用什么擦干我的眼泪 莎士比亚全集 工业纸巾 还是你同样泛红的眼睛 —— 4.19 一、⭐【核心函数】定义大模型调用函数 call_large_model prompt:用户传入的提示词(如 “请分析这篇作文的主题”),指导模型执行任务 client&…...
Keil MDK中禁用半主机(No Semihosting)
在 ARM 编译器(如 Keil MDK) 中禁用半主机(Semihosting)并实现标准库的基本功能,需要以下步骤: 1. 禁用半主机 #pragma import(__use_no_semihosting) // 禁用半主机模式作用:防止标准库函数&…...
QML中的3D功能--纹理应用
Qt 3D 提供了强大的纹理支持,可以实现各种复杂的材质效果。以下是 Qt 3D 纹理开发的全面技术方案。 一、纹理处理的流程图 纹理处理关键步骤说明: 资源准备阶段 支持格式:PNG/JPG/KTX/DDS等 尺寸要求:建议2的幂次方(非强制) 纹理加载路径 qml Texture2D {source: "…...
LeetCode[459]重复的子字符串(KMP解法)
思路: 最近迷上了KMP算法,所以这道题也是来搞一下KMP算法,总所周知KMP是需要维护一个前缀表,KMP算法不是比较一个字符串包不包含另一个字符串的吗,这个重复字符串的题也能用?猫爷:毋庸置疑&…...
数据驱动未来:大数据在智能网联汽车中的深度应用
数据驱动未来:大数据在智能网联汽车中的深度应用 引言 随着智能网联汽车(Intelligent Connected Vehicles,ICV)的快速发展,数据已成为其核心驱动力。从实时交通数据到车辆传感器信息,大数据的深度应用正在让智能汽车更安全、更高效、更智能化。那么,大数据如何赋能智能…...
基于MCP的RAG系统实战:用Cursor+GroundX构建复杂文档问答引擎
在AI与文档处理的融合趋势下,基于MCP协议的RAG(Retrieval-Augmented Generation)系统为复杂文档的智能问答提供了全新解决方案。本文将详细解析如何通过Cursor编辑器(MCP客户端)与GroundX(MCP服务器)的组合,构建一个可处理科研文献、企业知识库的端到端问答系统,并提供…...
DSA数据结构与算法 4
第2章 排序技术 2.1 排序简介 排序是将数据按照特定顺序(升序或降序)排列的过程,它不仅是计算机科学中的基础操作,也是日常生活中不可或缺的工具。举个例子,想象一个图书馆里的书籍,如果这些书籍没有按照作…...
23种设计模式全解析及其在自动驾驶开发中的应用
一、创建型模式(5种) 目标:解耦对象创建过程,提升系统灵活性 模式名称核心思想典型场景自动驾驶应用示例工厂方法子类决定实例化对象类型日志系统、数据库连接器创建激光雷达/摄像头等传感器实例抽象工厂创建相关对象家族GUI组件…...
基于WiFi的智能教室数据监测系统的设计与实现
标题:基于WiFi的智能教室数据监测系统的设计与实现 内容:1.摘要 随着教育信息化的发展,对教室环境及设备数据监测的智能化需求日益增长。本文的目的是设计并实现一种基于WiFi的智能教室数据监测系统。方法上,采用WiFi模块实现数据的无线传输,…...