Java高性能并发利器-VarHandle
1. 什么是 VarHandle?
VarHandle
是 Java 9 引入的类,用于对变量(对象字段、数组元素、静态变量等)进行低级别、高性能的原子操作(如 CAS、原子读写)。它是 java.util.concurrent.atomic
和 sun.misc.Unsafe
的安全替代品,提供类型安全和规范化的内存顺序控制。
2. 获取 VarHandle 的 4 种方式
(1) 实例字段
class MyClass {private int value;// 创建 VarHandlestatic final VarHandle VALUE_HANDLE;static {try {VALUE_HANDLE = MethodHandles.privateLookupIn(MyClass.class, MethodHandles.lookup()).findVarHandle(MyClass.class, "value", int.class);} catch (Exception e) {throw new Error(e);}}
}
(2) 静态字段
class MyClass {static int staticValue;static final VarHandle STATIC_HANDLE;static {try {STATIC_HANDLE = MethodHandles.lookup().findStaticVarHandle(MyClass.class, "staticValue", int.class);} catch (Exception e) {throw new Error(e);}}
}
(3) 数组元素
int[] array = new int[10];
VarHandle arrayHandle = MethodHandles.arrayElementVarHandle(int[].class);// 操作数组元素
arrayHandle.set(array, 5, 100); // array[5] = 100
(4) 堆外内存
// 通过 ByteBuffer 的 VarHandle 访问堆外内存
ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
VarHandle bufferHandle = buffer.varHandle(int.class, 0);
bufferHandle.set(buffer.position(0), 123);
3. 内存顺序(Memory Order)详解
VarHandle
允许通过 AccessMode
控制内存操作顺序,解决指令重排序和可见性问题:
内存模式 | 描述 |
---|---|
Plain(普通) | 无任何内存屏障,可能被重排序(类似普通变量读写) |
Opaque(不透明) | 保证线程间的原子性,但不保证全局内存顺序(JDK 9+) |
Release/Acquire | 写操作(Release)对其他线程的读操作(Acquire)可见 |
Volatile(易变) | 完全按顺序执行,类似 volatile 关键字 |
示例:设置内存模式
// 以 volatile 模式读写
int value = (int) VALUE_HANDLE.getVolatile(myObject);
VALUE_HANDLE.setVolatile(myObject, newValue);// 以 Release/Acquire 模式操作
VALUE_HANDLE.setRelease(myObject, newValue); // 写操作对其他线程可见
int v = (int) VALUE_HANDLE.getAcquire(myObject); // 确保读到最新值
4. 核心原子操作
(1) CAS(Compare-And-Swap)
boolean success = VALUE_HANDLE.compareAndSet(myObject, expectedValue, newValue);
(2) 原子递增/递减
int oldValue = (int) VALUE_HANDLE.getAndAdd(myObject, 1); // 类似 i++
(3) 原子更新
int updated = (int) VALUE_HANDLE.getAndUpdate(myObject, v -> v * 2);
(4) 原子读取-修改-写入
int result = (int) VALUE_HANDLE.getAndBitwiseOr(myObject, 0b100); // 位操作
5. 高级用法示例
示例 1:实现无锁栈(Lock-Free Stack)
class LockFreeStack<T> {private static class Node<T> {T value;Node<T> next;}private volatile Node<T> top;private static final VarHandle TOP_HANDLE;static {try {TOP_HANDLE = MethodHandles.lookup().findVarHandle(LockFreeStack.class, "top", Node.class);} catch (Exception e) {throw new Error(e);}}public void push(T value) {Node<T> newNode = new Node<>();newNode.value = value;Node<T> oldTop;do {oldTop = top;newNode.next = oldTop;} while (!TOP_HANDLE.compareAndSet(this, oldTop, newNode));}public T pop() {Node<T> oldTop;Node<T> newTop;do {oldTop = top;if (oldTop == null) return null;newTop = oldTop.next;} while (!TOP_HANDLE.compareAndSet(this, oldTop, newTop));return oldTop.value;}
}
示例 2:高性能计数器
class Counter {private int count;private static final VarHandle COUNT_HANDLE;static {try {COUNT_HANDLE = MethodHandles.lookup().findVarHandle(Counter.class, "count", int.class);} catch (Exception e) {throw new Error(e);}}// 原子递增(比 AtomicInteger 更轻量)public int increment() {return (int) COUNT_HANDLE.getAndAdd(this, 1);}
}
6. 与 Unsafe
的对比
特性 | VarHandle | Unsafe |
---|---|---|
类型安全 | ✔️ 强类型检查 | ❌ 依赖偏移量和手动类型转换 |
内存顺序控制 | ✔️ 提供明确语义 | ❌ 需要开发者自行管理屏障 |
兼容性 | ✔️ 标准 API,长期支持 | ❌ 内部 API,可能被移除 |
访问权限 | ✔️ 受 MethodHandles.Lookup 限制 | ❌ 可绕过 Java 访问控制 |
7. 性能优化建议
- 优先使用
volatile
模式:在需要全局可见性时使用getVolatile/setVolatile
。 - 避免反射开销:将
VarHandle
定义为static final
常量。 - 减少 CAS 竞争:在高并发场景中,使用
VarHandle
配合回退策略(如指数退避)。
8. 常见问题
Q1:VarHandle 能否替代 AtomicInteger
?
是的!AtomicInteger
内部已用 VarHandle
实现(JDK 9+),但直接使用 VarHandle
可以避免包装类的开销。
Q2:如何处理私有字段?
使用 MethodHandles.privateLookupIn()
获取访问权限:
VarHandle handle = MethodHandles.privateLookupIn(MyClass.class, MethodHandles.lookup()).findVarHandle(MyClass.class, "privateField", int.class);
Q3:VarHandle 支持哪些数据类型?
- 基本类型:
int
,long
,double
, 等 - 对象引用:
Object
- 数组:任意类型的数组元素
9. 总结
VarHandle
是 Java 并发编程的利器,适用于:
- 实现高性能无锁数据结构
- 替代
AtomicXXX
类减少开销 - 直接操作堆外内存或数组
10. 场景
场景 1:高性能环形缓冲区(无锁队列)
需求:实现多生产者-多消费者的环形缓冲区,避免锁竞争。
核心:利用 VarHandle
的 getAndAdd
和 compareAndSet
实现无锁指针推进。
public class RingBuffer<T> {private final Object[] buffer;private final int capacity;private volatile long head; // 消费者指针private volatile long tail; // 生产者指针private static final VarHandle HEAD_HANDLE;private static final VarHandle TAIL_HANDLE;private static final VarHandle BUFFER_HANDLE;static {try {MethodHandles.Lookup lookup = MethodHandles.lookup();HEAD_HANDLE = lookup.findVarHandle(RingBuffer.class, "head", long.class);TAIL_HANDLE = lookup.findVarHandle(RingBuffer.class, "tail", long.class);BUFFER_HANDLE = MethodHandles.arrayElementVarHandle(Object[].class);} catch (Exception e) {throw new Error(e);}}public RingBuffer(int capacity) {this.capacity = capacity;this.buffer = new Object[capacity];}// 生产者写入(多线程安全)public boolean offer(T item) {long currentTail;long newTail;do {currentTail = (long) TAIL_HANDLE.getVolatile(this);newTail = currentTail + 1;if (newTail - head >= capacity) return false; // 队列已满} while (!TAIL_HANDLE.compareAndSet(this, currentTail, newTail));// 写入数据(使用 Release 模式保证可见性)BUFFER_HANDLE.setRelease(buffer, (int) (currentTail % capacity), item);return true;}// 消费者读取(多线程安全)public T poll() {long currentHead;long newHead;do {currentHead = (long) HEAD_HANDLE.getVolatile(this);if (currentHead >= tail) return null; // 队列为空newHead = currentHead + 1;} while (!HEAD_HANDLE.compareAndSet(this, currentHead, newHead));// 读取数据(Acquire 模式确保读取到最新值)return (T) BUFFER_HANDLE.getAcquire(buffer, (int) (currentHead % capacity));}
}
场景 2:线程安全的延迟初始化(替代双重检查锁)
需求:实现线程安全的单例,避免 synchronized
开销。
核心:用 VarHandle
的 compareAndExchange
替代双重检查锁,性能更高。
public class LazyInitializer {private volatile Resource resource;private static final VarHandle RESOURCE_HANDLE;static {try {RESOURCE_HANDLE = MethodHandles.lookup().findVarHandle(LazyInitializer.class, "resource", Resource.class);} catch (Exception e) {throw new Error(e);}}public Resource getResource() {Resource res = resource;if (res == null) {Resource newRes = createResource();// 原子替换:若当前值为 null,则替换为 newResres = (Resource) RESOURCE_HANDLE.compareAndExchange(this, null, newRes);if (res == null) {res = newRes;}}return res;}private Resource createResource() {return new Resource(); // 初始化逻辑}
}
场景 3:自定义原子浮点操作
需求:Java 原生的 Atomic
类不支持 float
,用 VarHandle
实现原子浮点更新。
核心:通过 Float.floatToIntBits
和 VarHandle
的 getAndBitwiseXor
模拟原子操作。
public class AtomicFloat {private volatile int bits; // 用 int 存储 float 的二进制形式private static final VarHandle BITS_HANDLE;static {try BITS_HANDLE = MethodHandles.lookup().findVarHandle(AtomicFloat.class, "bits", int.class);} catch (Exception e) {throw new Error(e);}}public float get() {return Float.intBitsToFloat((int) BITS_HANDLE.getVolatile(this));}public void set(float value) {BITS_HANDLE.setVolatile(this, Float.floatToIntBits(value));}// 原子加法(通过CAS实现)public float addAndGet(float delta) {int prevBits, newBits;do {prevBits = (int) BITS_HANDLE.getVolatile(this);float prevValue = Float.intBitsToFloat(prevBits);float newValue = prevValue + delta;newBits = Float.floatToIntBits(newValue);} while (!BITS_HANDLE.compareAndSet(this, prevBits, newBits));return Float.intBitsToFloat(newBits);}
}
场景 4:状态机的高效切换
需求:多线程环境下安全切换状态,支持从 INIT
→ RUNNING
→ STOPPED
。
核心:用 VarHandle
的 compareAndSet
确保状态转换的原子性。
public class StateMachine {private volatile int state; // 0: INIT, 1: RUNNING, 2: STOPPEDprivate static final VarHandle STATE_HANDLE;static {try {STATE_HANDLE = MethodHandles.lookup().findVarHandle(StateMachine.class, "state", int.class);} catch (Exception e) {throw new Error(e);}}public boolean start() {return STATE_HANDLE.compareAndSet(this, 0, 1);}public boolean stop() {int currentState;do {currentState = (int) STATE_HANDLE.getVolatile(this);if (currentState != 1) return false; // 必须处于 RUNNING 状态} while (!STATE_HANDLE.compareAndSet(this, 1, 2));return true;}
}
场景 5:内存映射文件的原子操作
需求:直接操作内存映射文件(如实现高性能IPC)。
核心:通过 ByteBuffer
的 VarHandle
实现内存映射区域的原子读写。
public class MemoryMappedFile {private final ByteBuffer buffer;private static final VarHandle INT_HANDLE = MethodHandles.byteBufferViewVarHandle(int.class, ByteOrder.nativeOrder());public MemoryMappedFile(String path, int size) throws IOException {try (FileChannel channel = FileChannel.open(Path.of(path), StandardOpenOption.READ, StandardOpenOption.WRITE)) {buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, size);}}//写入 int 值public void atomicWrite(int value) {INT_HANDLE.setVolatile(buffer, 0, value); // 在偏移量0处写入}// 原子读取 int 值public int atomicRead() {return (int) INT_HANDLE.getVolatile(buffer, 0);}//更新public boolean compareAndSwap(int expected, int newValue) {return INT_HANDLE.compareAndSet(buffer, 0, expected, newValue);}
}
场景 6:线程安全的位图索引
需求:多线程环境下高效管理位图(如布隆过滤器)。
核心:使用 VarHandle
的原子位操作(getAndBitwiseOr
/ getAndBitwiseAnd
)。
public class ConcurrentBitMap {private final long[] bits;private static final VarHandle ARRAY_HANDLE = MethodHandles.arrayElementVarHandle(long[].class);public ConcurrentBitMap(int size) {bits = new long[(size + 63) / 64];}// 原子设置某一位public void setBit(int index) {int arrayIndex = index / 64;int bitOffset = index % 64;long mask = 1L << bitOffset;ARRAY_HANDLE.getAndBitwiseOr(bits, array mask);}// 原子清除某一位public void clearBit(int index) {int arrayIndex = index / 64;int bitOffset = index % 64;long mask = ~(1L << bitOffset);ARRAY_HANDLE.getAndBitwiseAnd(bits, arrayIndex, mask);}
}
场景 7:自定义原子引用数组
需求:实现类似 AtomicReferenceArray
但更轻量的线程安全数组。
核心:利用 VarHandle
直接操作数组元素。
public class SafeArray<T> {private final Object[] array;private static final VarHandle ARRAY_HANDLE;static {ARRAY_HANDLE = MethodHandles.arrayElementVarHandle(Object[].class);}public SafeArray(int size) {array = new Object[size];}// 原子设置元素public void set(int index, T value) {ARRAY_HANDLE.setVolatile(array, index, value);}// 原子获取元素public T get(int index) {return (T) ARRAY_HANDLE.getVolatile(array, index);}// CAS 更新public boolean compareAndSet(int index, T expected, T newValue) {return ARRAY_HANDLE.compareAndSet(array, index, expected, newValue);}
}
场景 8:高效计数器组(Striped Counter)
需求:减少高并发下计数器的缓存行竞争。
核心:使用 VarHandle
分散计数器到不同内存位置。
public class StripedCounter {private final long[] counts;private static final VarHandle COUNT_HANDLE;static {COUNT_HANDLE = MethodHandles.arrayElementVarHandle(long[].class);}public StripedCounter(int stripes) {counts = new long[stripes];}// 根据线程ID选择不同的计数器槽public void increment() {int index = (Thread.currentThread().hashCode() & 0x7FFFFFFF) % counts.length;COUNT_HANDLE.getAndAdd(counts, index, 1L);}// 获取总和(可能不精确)public long sum() {long sum = 0;for (long c : counts) {sum += c;}return sum;}
}
最佳实践总结
- 优先选择
VarHandle
而非Unsafe
:前者是标准 API,且类型安全。 - 明确内存顺序:根据场景选择
plain
/opaque
/release-acquire
/volatile
。 - 减少 CAS 竞争:使用回退策略(如指数退避)或分散热点(Striping)。
- 注意可见性:跨线程操作必须使用
volatile
或release-acquire
模式。
11.底层优化方案
1. 伪共享(False Sharing)与缓存行对齐
问题根源
- 伪共享:两个线程频繁修改位于同一缓存行(通常 64 字节)的不同变量,导致缓存行无效化,引发 CPU 缓存同步开销。
- 后果:高并发场景下性能急剧下降,即使变量逻辑无关。
解决方案:缓存行填充
通过填充变量,确保每个核心变量独占一个缓存行。
代码示例:线程安全的高性能计数器(避免伪共享)
import java.lang.invoke.VarHandle;
.lang.invoke.MethodHandles;class PaddedCounter {// 核心计数变量 + 前后填充(确保独占缓存行)private volatile long p1, p2, p3, p4, p5, p6, p7; // 前填充(56字节)private volatile long count;private volatile long q1, q2, q3, q4, q5, q6, q7; // 后填充(56字节)private static final VarHandle COUNT_HANDLE;static {try {COUNT_HANDLE = MethodHandles.lookup().findVarHandle(PaddedCounter.class, "count", long.class);} catch (Exception e) {throw new Error(e);}}public void increment() {COUNT_HANDLE.getAndAdd(this, 1L);}public long get() {return (long) COUNT_HANDLE.getVolatile(this);}
}
优化原理
- 填充字段:
p1
-p7
和q1
-q7
每个long
占 8 字节,共 7 * 8=56 字节,加上count
的 8 字节,总计 56+56=120 字节,远超 64 字节缓存行,确保count
独占一行。 - Volatile 模式:
getVolatile
保证跨线程可见性,但填充避免了伪共享导致的性能损失。
2. 使用 @Contended
注解(JVM 自动填充)
Java 8+ 提供 @sun.misc.Contended
注解,由 JVM 自动填充字段(需启用 -XX:-RestrictContended
)。
代码示例
import sun.misc.Contended;class ContendedCounter {@Contended // JVM 自动填充private volatile long count;private static final VarHandle COUNT_HANDLE;static {try {COUNT_HANDLE = MethodHandles.lookup().findVarHandle(ContendedCounter.class, "count", long.class);} catch (Exception e) {throw new Error(e);}}public void increment() {COUNT_HANDLE.getAndAdd(this, 1L);}
}
3. 内存屏障(Memory Barrier)的精细化控制
VarHandle
的内存模式(plain
/opaque
/release
/acquire
/volatile
)直接影响 JVM 插入的内存屏障指令数量。
内存模式 | 内存屏障 | 性能开销 | 适用场景 |
---|---|---|---|
Plain | 无屏障 | 最低 | 单线程或线程封闭变量 |
Opaque | 原子性屏障(无顺序保证) | 低 | 线程间通信,但不要求全局顺序 |
Release | 写屏障(StoreStore + StoreLoad) | 中 | 发布数据到其他线程 |
Acquire | 读屏障(LoadLoad + LoadStore) | 中 | 获取其他线程发布的数据 |
Volatile | 全屏障(Load + Store) | 最高 | 严格的 happens-before 语义 |
示例:选择最轻量级屏障
class LightweightSync {private int value;private static final VarHandle VALUE_HANDLE;static {try {VALUE_HANDLE = MethodHandles.lookup().findVarHandle(LightweightSync.class, "value", int.class);} catch (Exception e) {throw new Error(e);}}// 使用 Release 模式写入(仅插入必要屏障)public void publish(int newValue) {VALUE_HANDLE.setRelease(this, newValue);}// 使用 Acquire 模式读取public int read() {return (int) VALUE_HANDLE.getAcquire(this);}
}
4. 直接内存(堆外内存)操作优化
通过 VarHandle
直接操作堆外内存(如 Netty 的 ByteBuf
),避免 JVM 堆 GC 开销。
示例:高性能堆外计数器
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.lang.invoke.VarHandle;public class DirectMemoryCounter {private final ByteBuffer buffer;private static final VarHandle LONG_HANDLE;static {LONG_HANDLE = MethodHandles.byteBufferViewVarHandle(long[].class, ByteOrder.nativeOrder());}public DirectMemoryCounter() {buffer = ByteBuffer.allocateDirect(64); // 分配 64 字节堆外内存buffer.order(ByteOrder.nativeOrder());}// 原子递增(无锁)public long increment() {return (long) LONG_HANDLE.getAndAdd(buffer, 0, 1L);}// 直接读取public long get() {return (long) LONG_HANDLE.getVolatile(buffer, 0);}
}
5. 字段偏移量硬编码(极端优化)
在已知 JVM 实现的情况下,直接计算字段偏移量(类似 Unsafe
),但牺牲可移植性。
示例:手动计算偏移量
class UnsafeStyleCounter {private static final long VALUE_OFFSET;private volatile long value;static {try {// 假设对象头为 12 字节(32位 JVM)或 16 字节(64位 JVM)VALUE_OFFSET = 16; // 手动计算偏移量(极端情况)} catch (Exception e) {throw new Error(e);}}private static final VarHandle VALUE_HANDLE = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.nativeOrder()).withInvokeExactBehavior().withInvokeBehavior().withCoordinateConversion((addr, coord) -> addr + VALUE_OFFSET);public void increment() {VALUE_HANDLE.getAndAdd(this, 0L, 1L);}
}
6. 性能测试与工具
检测伪共享
- Linux Perf:
perf stat -e cache-misses java YourProgram
- Intel VTune:分析缓存行竞争(False Sharing 事件)。
- JMH:基准测试框架,量化不同优化手段的效果。
JMH 基准测试示例
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class CounterBenchmark {private PaddedCounter paddedCounter = new PaddedCounter();private ContendedCounter contendedCounter = new ContendedCounter();@Benchmarkpublic void paddedIncrement(Blackhole bh) {paddedCounter.increment();bh.consume(paddedCounter.get());}@Benchmarkpublic void contendedIncrement(Blackhole bh) {contendedCounter.increment();bh.consume(contendedCounter.get());}
}
总结:最佳实践
- 优先解决伪共享:通过填充或
@Contended
确保热点变量独占缓存行。 - 选择最小内存屏障:根据场景使用
release
/acquire
替代volatile
。 - 堆外内存优化:直接操作
ByteBuffer
或Unsafe
分配的内存。 - 量化优化效果:通过 JMH 验证优化是否有效,避免过度设计。
相关文章:
Java高性能并发利器-VarHandle
1. 什么是 VarHandle? VarHandle 是 Java 9 引入的类,用于对变量(对象字段、数组元素、静态变量等)进行低级别、高性能的原子操作(如 CAS、原子读写)。它是 java.util.concurrent.atomic 和 sun.misc.…...
关于读完《毛泽东选集》的一些思考迭代
看完毛选前四卷,从革命初期一直讲到抗战胜利,共75.8W字,花费67个小时读完。从1925年发表的“中国社会各阶级的分析”,跨越100年,通过67个小时向主席学习到: 实事求是 从实践中来再到实践中去 用辩证与发展…...
机器学习 第一章
🧠 机器学习 第一章 一、什么是机器学习 (Machine Learning) 让计算机自己从数据中学习出规律,无需人手写规则 输入: 特征 x输出: 标签 y学习目标: 学习出 f(x) 等价于 y 二、三大类型任务 类型英文特点示例回归Regression输出是连续值房价预测分类Cla…...
LVS+Keepalived+DNS 高可用项目
项目架构 主机规划 主机IP角色软件lb-master172.25.250.105主备负载均衡器ipvsadm,keepalivedlb-backup172.25.250.106同时做web和dns调度ipvsadm,keepaliveddns-master172.25.250.107VIP:172.25.250.100binddns-slave172.25.250.108LVS DNS…...
app逆向专题三:adb工具的使用
app逆向专题三:adb工具的使用 一、adb工具的配置二、adb工具的下载与安装 一、adb工具的配置 adb它是一个通用命令行工具,它可以作为Android与PC端连接的一个桥梁,所以adb又成为Android调试桥,用户可以通过adb在电脑上对Android设…...
CAD导入arcgis中保持面积不变的方法
1、加载CAD数据,选择面数据,如下: 2、加载进来后,右键导出数据,导出成面shp数据,如下: 3、选择存储路径,导出面后计算面积,如下: 4、与CAD中的闭合线面积核对…...
提示词 (Prompt)
引言 在生成式 AI 应用中,Prompt(提示)是与大型语言模型(LLM)交互的核心输入格式。Prompt 的设计不仅决定了模型理解任务的准确度,还直接影响生成结果的风格、长度、结构与可控性。随着模型能力和应用场景…...
并查集(Java模板及优化点解析)
并查集 一、核心思想 并查集(Union-Find)是一种处理不相交集合合并与查询的高效数据结构,核心功能包括: 合并(Union):将两个不相交集合合并为一个集合。查询(Find)&am…...
本地部署大模型(ollama模式)
分享记录一下本地部署大模型步骤。 大模型应用部署可以选择 ollama 或者 LM Studio。本文介绍ollama本地部署 ollama官网为:https://ollama.com/ 进入官网,下载ollama。 ollama是一个模型管理工具和平台,它提供了很多国内外常见的模型&…...
【JavaEE】TCP流套接字编程
目录 API 1.Socket类(客户端) 2.ServerSocket类(服务端) 创建回显服务器-客户端 服务器引入多线程 服务器引入线程池 解疑惑 长短连接 在Java中,TCP流套接字是基于TCP协议实现的网络通信方式,提供面向连接、可靠、有序的双向字节流传输。 API T…...
SQL问题分析与诊断(8)——分析方法1
8.4. 方法 8.4.1. 分析Cost方法 8.4.1.1. 方法说明 SQL Server中,通过阅读和分析SQL语句的评估查询计划,才是现实SQL优化工作中经常被采用的方法。然而,与Oracle等关系库类似,我们对SQL语句的查询计划进行阅读和分析时,首先要做的就是对SQL语句的整个查询计划进行快速的…...
【深度学习基础】神经网络入门:从感知机到反向传播
摘要 神经网络是深度学习的核心!本文将带你从零开始理解神经网络的基本原理,包括感知机模型、激活函数选择、反向传播算法等核心概念,并通过Python实现一个简单的全连接神经网络。文末提供《神经网络公式推导手册》和实战项目资源包…...
linux RCU技术
RCU(Read-Copy-Update)是Linux内核中的一种同步机制,用于在多核处理器环境中实现无锁读取和延迟更新。Linux RCU(Read-Copy-Update)技术通过一种高效的同步机制来处理并发冲突,确保在多核环境中读者和写者对…...
Hadoop文件操作指南:深入解析文件操作
1 Hadoop文件系统概述 Hadoop分布式文件系统(HDFS)是Hadoop生态的核心存储组件,专为大规模数据集设计,具有高容错性和高吞吐量特性。 HDFS核心特性: 分布式存储:文件被分割成块(默认128MB)分布存储多副本机制:每个块默认3副本&…...
【AI论文】VCR-Bench:视频链式思考推理的综合评估框架
摘要:思想链(CoT)推理的进步显著增强了大型语言模型(LLMs)和大型视觉语言模型(LVLMs)的能力。 然而,目前仍然缺乏一个严格的视频CoT推理评估框架。 目前的视频基准测试无法充分评估推…...
激光雷达点云动态目标剔除算法
剔除点云地图中动态目标的方法可分为基于体素、基于视点可见性和基于深度学习的方法。基于体素的方法通过点云地图体素占用率或点云地图体素与单帧点云数据差异剔除动态目标。 OctoMap算法在使用单帧点云数据构建点云地图的过程中,不断更新体素占用率,直…...
第五篇:Python面向对象编程(OOP)深度教程
1. 类与对象 1.1 基本概念 类是创建对象的蓝图,定义了对象的属性(数据)和方法(行为)。对象是类的实例化实体,每个对象拥有独立的属性值和共享的类方法 示例:定义Dog类 class Dog:species = "Canis familiaris" …...
Java IO精讲:从传统IO到NIO的深度探索
一、Java IO概述 Java IO(Input/Output) 是Java处理输入输出的核心API,涵盖文件操作、网络通信等场景。其发展分为三个阶段: 传统IO (java.io):基于流模型,阻塞式处理NIO (java.nio):New IO&a…...
效率工具- git rebase 全解
一、前言 对于git rebase 一直不太了解,这几天想着提高下git提交质量,就发现了这个好用的指令,顺便记录一下,好加深记忆 贴出官方文档以便大家进一步学习 Git 二、rebase是作用 rebase 官方解释为变基,可以理解为移动你的分支根节点,维护一个更好的提交记录。rebase把你当前…...
开启深度学习之旅
深度学习作为人工智能领域最激动人心的分支之一,正在改变我们与科技互动的方式。本文将为您提供深度学习的入门指南,帮助您踏上这一充满可能性的旅程。 一、深度学习基础概念 深度学习是机器学习的一个子集,它使用多层神经网络来模拟人脑的…...
JMeter的关联
关联:上一个请求的响应结果和下一个请求的数据有关系 xpath提取器 适用场景 HTML/XML文档结构化数据: 适用于从HTML或XML文档中提取结构化数据。例如,提取表格中的数据、列表中的项目等。示例:从HTML表格中提取所有行数据。 …...
jvm内存如何调优
以下是关于JVM内存调优的一些关键方法和最佳实践: 1. 堆内存配置 • 初始堆大小与最大堆大小: • 使用 -Xms 和 -Xmx 参数设置初始堆大小和最大堆大小。建议将两者设置为相同的值,以避免堆的动态扩展带来的性能开销。 • 堆内存大小通常建…...
[特殊字符] 第十四讲 | 空间异质性检验与地统计局部指标(LISA)应用
📌 关键词:空间异质性、LISA、局部Morans I、空间聚集、冷热点分析、GeoDa、R语言 🧠 导语:空间现象为何“不一样”? 在地理学与农学研究中,我们经常遇到“某地污染严重,而邻近区域却很轻微”的…...
【时时三省】(C语言基础)选择结构程序综合举例
山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 下面综合介绍几个包含选择结构的应用程序。 例题1: 写一程序,判断某一年是否为闰年。 程序1: 先画出判别闰年算法的流程图,见下图用变量le…...
【软考系统架构设计师】软件工程知识点
1、 软件开发生命周期 软件定义时期:包括可行性研究和详细需求分析过程,任务是确定软件开发工程必须完成的总目标,具体分为问题定义、可行性研究、需求分析等 软件开发时期:软件的设计与实现,分为概要设计、详细设计、…...
C#容器源码分析 --- Queue<T>
Queue<T> 是 System.Collections.Generic 命名空间下的先进先出(FIFO)动态集合,其核心实现基于循环数组,通过维护头尾指针实现高效入队和出队操作。 .Net4.8 Queue<T>源码地址:queue.cs (microso…...
redis 进阶
前篇 1,持久化 定义:将内存中的数据写入到磁盘,防止数据丢失——如果我门没有使用持久化技术,下次重新启动REDIS的时候只有空的redis没有任何东西 RDB 定义:在指定的时间间隔内将内存中的所有数据集以文件的形式写…...
python文件打包无法导入ultralytics模块
💥打包的 .exe 闪退了?别慌!教你逐步排查 PyInstaller 打包的所有错误! 🛠 运行 .exe 查看报错信息✅ 正确姿势: ⚠ importlib 动态导入导致打包失败❓什么是动态导入?✅ 解决方式: …...
c++清理内存
c清理内存 1.内存状态监控 实时显示物理内存/备用内存使用情况 2.单进程内存清理 清理当前进程工作集内存 3.系统级内存清理 清理备用列表、已修改页、组合列表 4.全局进程优化 强制清理所有进程的工作集 5.权限管理 启用调试权限以执行敏感操作 6.用户交互 控制台菜单操作与实…...
操作系统之进程同步
1.什么是进程同步,为什么要引入进程同步? 进程同步是指多个进程在执行次序上进行协调,使它们按一定的规则共享资源和相互合作。引入进程同步是为了避免并发进程因资源竞争而产生数据不一致、混乱等问题,确保系统的稳定性和正确性。 2.同步…...
论文精度:基于LVNet的高效混合架构:多帧红外小目标检测新突破
论文地址:https://arxiv.org/pdf/2503.02220 目录 一、论文背景与结构 1.1 研究背景 1.2 论文结构 二、核心创新点解读 2.1 三大创新突破 2.2 创新结构原理 2.2.1 多尺度CNN前端 2.2.2 视频Transformer设计 三、代码复现指南 3.1 环境配置 3.2 数据集准备 3.3 训…...
C语言--汉诺塔问题
汉诺塔问题是一个典型的递归问题。 递归问题的基本思想:将问题逐步化简为相同思路但是规模更小的问题,直到问题可以直接解决 递归的关键在于基准情形和递归步骤,基准情形也就是退出条件,递归步骤也就是把问题简化为子问题的过程。…...
深度剖析SSD多段L2P表查找加速技术
在固态硬盘(SSD)控制器中,逻辑块地址(LBA)需要通过映射表(L2P Table)映射到NAND闪存的物理地址(PA)。随着SSD容量的增长,L2P表的大小也随之增加,这给查找操作带来了性能挑战。 在SSD控制器中,LBA需借助L2P表映射为NAND物理地址。映射表最小规模为 (O(n * \lg (n)))…...
【sgSpliter】自定义组件:可调整宽度、高度、折叠的分割线
特性: 允许设置显示折叠按钮允许设置折叠线按钮位置允许设置当拖拽区域到0,再点击箭头展开的默认宽度允许设置当拖拽宽度小于此宽度,自动折叠到0允许设置指定最小宽度允许设置指定最大宽度允许设置按钮风格:白色背景default、蓝色背景blue允许…...
图像预处理-插值方法
一.插值方法 当我们对图像进行缩放或旋转等操作时,需要在新的像素位置上计算出对应的像素值。 而插值算法的作用就是根据已知的像素值来推测未知位置的像素值。 1.1 最近邻插值 CV2.INTER_NEAREST 其为 warpAffine() 函数的参数 flags 的其一,表示最近…...
Adruino:传感器及步进电机
一、传感器 1、温湿度传感器 DHT11它采用专用的数字采集技术和温湿度传感器技术,包括一个电阻式感湿元件和NTC测温元件,并与一个高性能的8位单片机连接。 (1).引脚介绍 名称解释VCC供电引脚3~5VGND接地引脚DATA串行数据单总线 二、电机 1…...
leetcode 2787. Ways to Express an Integer as Sum of Powers
题目描述 这道题是0-1背包问题。可以理解为,有一个最大容量是n的背包,有n个物品,第i个物品的重量是i^x,问装满背包有多少种装法。题目要求必须是互不相同的数的x次幂的和等于n,那就表示每个数只能用一次,也…...
React 获得dom节点和组件通信
通过REF 实例对象的.current属性获得绑定的DOM节点 组件通信 组件通信 1 父传子 父组件传递数据 子组件接受数据 通过pros对象接受 子组件的形参列表props只读 props中数据不可修改 特殊情况 在子传父的过程中没有直接给子组件添加属性,而是向父组件中添加其他…...
AF3 ProteinDataset类的get_anchor_ind方法解读
AlphaFold3 protein_dataset 模块 ProteinDataset 类 get_anchor_ind 方法是一个 @staticmethod 静态方法,用来获取“锚定残基(anchor residues)”的索引,目的是在蛋白质序列中被遮蔽(masked)的区域两端找到“已知(known)”的残基,以便后续作为上下文参考。 源代码:…...
JavaScript异常机制与严格模式
目录 JavaScript 异常机制 1. 基本语法:try...catch...finally 2. 抛出异常:throw 3. 错误对象属性 4. 同步代码的异常处理 5. 异步代码的异常处理 5.1 回调函数 5.2 Promise 5.3 全局未捕获的 Promise 错误 6. 全局错误处理 7. 自定义错误与…...
【数据结构与算法】包装类初识泛型
文章目录 一.包装类1.1基本数据类型和对应的包装类1.2装箱和拆箱1.3自动拆箱和自动装箱【面试题】 二.什么是泛型三.引出泛型3.1 语法 四. 泛型的使用4.1 语法格式4.2 示例4.3 类型推导(Type Inference) 五. 裸类型(Raw Type) (了解即可)5.1 说明 六. 泛…...
Linux--进程信号
目录 1. 信号快速认识 1-1 ⽣活⻆度的信号 1-2 技术应⽤⻆度的信号 1-2-1 ⼀个样例 1-2-2 ⼀个系统函数 1-3 信号概念 1-3-1 查看信号编辑 1-3-2 信号处理 2. 产⽣信号 2-1 通过终端按键产⽣信号 2-1-1 基本操作 2-2 调⽤系统命令向进程发信号 2-3 使⽤函数产⽣…...
Skynet入门(二)
常用接口说明 接口说明newservice(name, …)启动一个name的新服务,并返回新服务的地址start(func)用func初始换服务。编写服务时,都会写一句skynet.start,并在func写一些初始化代码dispatch(type, func为type类型的消息设定处理函数funcsend…...
TDengine 可靠性保障:数据持久化与容灾备份(二)
四、容灾备份策略揭秘 (一)主从复制与故障转移 在 TDengine 的高可用性架构中,主从复制是一种极为关键的设计模式,它就像是数据的 “安全复制机”,将数据从主节点精准无误地复制到多个从节点 。在这个过程中…...
一文讲透大模型强化学习基础:PPO、DPO、GRPO
DeepSeek-R1 的强化学习方案中,其亮点之一在于通过 GRPO 算法取代RLHF 常用的 PPO,通过尽可能减少人类标注数据,设计纯 RL 的环境,用精心设计的奖励机制来训练模型自己学会推理。 那么什么是PPO、GRPO,其产生的背景、…...
第十六届蓝桥杯大赛软件赛省赛 Python 大学 B 组 部分题解
题面链接Htlang/2025lqb_python_b 个人觉得今年这套题整体比往年要简单许多,但是G题想简单了出大问题,预估50101015120860,道阻且长,再接再厉 A: 攻击次数 答案:103?181?题目没说明白每回合是…...
5分钟搭建一个在线客服网站!免费!
快速搭建在线客服网站完整教程 本文将手把手教你如何从零开始搭建一个功能完善的在线客服系统,整个过程简单快速,适合新手操作。 一、服务器选购指南 注册雨云账号 如果您尚未注册雨云账号,可以通过以下方式获取优惠: 注册链…...
【测试】-- 测试用例
文章目录 1. 测试用例1.1 概念 2. 设计测试用例的万能公式2.1 常规思考逆向思维发散性思维2.2 万能公式 3. 设计测试用例的方法3.1 具体的设计⽅法3.1.1 等价类3.1.2 边界值3.1.3 正交法3.1.3.1 如何设计正交表 3.1.4 判定表法3.1.4.1 根据判定表法设计测用例的步骤 3.1.5 场景…...
深度剖析循环码解码:从原理到纠错实践
一、引言 循环码作为线性分组码中的重要一员,凭借其出色的纠错和检测能力,在通信领域得到了广泛应用。本文将深入探讨循环码的解码过程,详细阐述其纠错和检测的机理。 二、循环码基础回顾 2.1 循环码的定义与性质 循环码是一类具有循环特性的线性分组码,即任一码组循环…...
MySQL面试题及答案,2025最新整理
文章目录 前言1.InnoDB 与 MyISAM 在事务和索引方面有哪些主要区别?2.简述 MySQL 的事务隔离级别及其对并发问题的解决情况?3.在使用 MySQL 索引时,如何避免索引失效,提高查询效率? 前言 本文围绕 MySQL面试题及答案&…...