多线程编程中的锁策略
目录
1.悲观锁vs乐观锁
关键总结
悲观锁:
乐观锁:
选择建议
用 悲观锁 当:
用 乐观锁 当:
2.重量级锁vs轻量级锁
选择建议
用 轻量级锁:
用 重量级锁:
3.挂起等待锁vs自旋锁
关键细节说明
选择建议
4.普通互斥锁vs读写锁
读写锁互斥规则详解
普通互斥锁 vs 读写锁对比
5.可重入锁vs不可重入锁
选择建议
6.公平锁vs不公平锁
1) 公平锁和不公平锁的对比
2)选择建议
7.锁升级
8.锁优化
9.锁的粗化
10.synchronized
11.reentrantlock和synchronized的对比
锁策略(Locking Strategies)是多线程编程中用于控制并发访问共享资源的核心机制。不同的锁策略在性能、公平性、复杂度等方面有显著差异。
以下来介绍几组常见的锁策略:
1.悲观锁vs乐观锁
悲观锁:在加锁的时候预测接下来的竞争会非常激烈,所以就需要针对这种激烈的竞争情况做一些准备工作:每次拿数据的时候都会上锁,这样别人想要拿数据的时候就会阻塞知道它拿到锁。
乐观锁:在加锁的时候预测接下来的竞争不会非常激烈,也就一般不会发生并发冲突,不必多做准备。在数据进行提交更新的时候再检测是否产生并发冲突。
| 特性 | 悲观锁 | 乐观锁 |
|---|---|---|
| 核心思想 | 假设并发冲突一定会发生,因此先加锁再访问数据。 | 假设并发冲突较少发生,因此不加锁,通过版本号/CAS机制检测冲突。 |
| 实现方式 | 直接加锁(如 synchronized、ReentrantLock、数据库 SELECT FOR UPDATE)。 | 无锁机制(如 CAS、版本号校验、AtomicXXX 类、数据库 乐观并发控制)。 |
| 阻塞行为 | ❗ 会阻塞其他线程(未获取锁的线程必须等待)。 | ✅ 无阻塞,线程直接操作数据,冲突时通过重试或回滚解决。 |
| 适用场景 | 写多读少(如银行转账、库存扣减等强一致性场景)。 | 读多写少(如缓存、统计计数等低冲突场景)。 |
| 性能开销 | 高(锁竞争、上下文切换、死锁风险)。 | 低(无锁竞争,但冲突频繁时重试开销增大)。 |
| 数据一致性 | 强一致性(锁内操作串行化)。 | 最终一致性(冲突时需业务层处理)。 |
| 典型实现 | Java: synchronized、ReentrantLock数据库: SELECT FOR UPDATE。 | Java: AtomicInteger、StampedLock数据库: 版本号字段、CAS操作。 |
| 优缺点 | ✅ 保证强一致性 ❌ 吞吐量低,可能死锁。 | ✅ 高并发性能 ❌ 需处理冲突,可能活锁或重试饥饿。 |
关键总结
-
悲观锁:
-
“先保护再操作”,适合强一致性场景,但性能较差。
-
例如:
synchronized关键字、数据库行锁。
-
-
乐观锁:
-
“先操作再校验”,适合高并发读场景,冲突少时性能极高。
-
例如:
CAS操作、StampedLock的乐观读模式。
-
选择建议
-
用 悲观锁 当:
-
写操作频繁,或冲突概率高(如支付系统)。
-
业务逻辑复杂,需严格保证数据一致性。
-
-
用 乐观锁 当:
-
读多写少,且冲突概率低(如商品浏览统计)。
-
追求高吞吐量,能容忍重试或短暂不一致。
-
2.重量级锁vs轻量级锁
重量级锁:应对悲观的场景,此时就要付出更多的代价,更低效。
轻量级锁:应对乐观的场景,此时付出的代价更小,更高效。
| 特性 | 重量级锁 | 轻量级锁 |
|---|---|---|
| 锁级别 | 最高级别的锁(如操作系统级互斥锁) | JVM 层面的优化锁(基于 CAS 自旋) |
| 实现原理 | 通过操作系统内核的 互斥量(Mutex) 实现,涉及用户态/内核态切换。 | 通过 CAS(Compare-And-Swap) 和 线程栈中的锁记录(Lock Record) 实现。 |
| 阻塞方式 | 未获取锁的线程会 直接挂起(进入内核态等待队列),由操作系统调度唤醒。 | 先通过 自旋(忙等待) 尝试获取锁,失败后才升级为重量级锁。 |
| 性能开销 | 高(上下文切换、内核态切换、CPU 调度延迟)。 | 低(无系统调用,仅在用户态自旋)。 |
| 适用场景 | 高竞争、长临界区(如长时间持有锁的复杂操作)。 | 低竞争、短临界区(如快速计算的简单操作)。 |
| 锁升级 | 是锁膨胀的最终状态(轻量级锁/偏向锁失败后升级)。 | 是偏向锁失败后的中间状态,可能进一步升级为重量级锁。 |
| 典型例子 | synchronized 在竞争激烈时的最终状态。 | synchronized 在低竞争时的优化状态。 |
| 优点 | 严格保证线程安全,适合高并发冲突场景。 | 减少内核态开销,提高短任务性能。 |
| 缺点 | 吞吐量低,响应延迟高。 | 自旋浪费 CPU(长时间自旋可能反而降低性能)。 |
选择建议
-
用 轻量级锁:
-
代码块执行时间极短(如计数器递增)。
-
线程竞争概率低(如局部变量同步)。
-
-
用 重量级锁:
-
临界区执行时间长(如数据库事务)。
-
竞争激烈(如全局缓存更新)。
-
3.挂起等待锁vs自旋锁
挂起等待锁:(重量级锁的经典实现)一旦发生竞争,获取不到锁,就进入阻塞状态。
自旋锁:(轻量级锁的经典实现)一旦发生竞争,获取不到锁,就循环请求,也就是“忙等”。发生在“乐观”情况下,锁竞争很小,即使“忙等”,很快也能获取锁,等待的时间也不会很长 ,消耗的资源也就不会很多。
| 特性 | 挂起等待锁(阻塞锁) | 自旋锁 |
|---|---|---|
| 实现原理 | 获取不到锁时,线程进入阻塞状态(WAITING),释放CPU资源 | 获取不到锁时,线程循环忙等待(自旋),不释放CPU |
| 响应速度 | 较慢(需要线程切换和唤醒) | 极快(无上下文切换) |
| CPU占用 | 低(线程挂起后不消耗CPU) | 高(持续占用CPU自旋) |
| 适用场景 | 锁持有时间较长(如I/O操作、复杂计算) | 锁持有时间极短(如CAS操作、简单计算) |
| 公平性 | 通常支持公平锁(按申请顺序获取锁) | 通常是非公平锁(竞争机制) |
| 锁升级 | 可能涉及内核态切换(如synchronized重量级锁) | 完全在用户态运行(无系统调用) |
| 典型实现 | Java的synchronized(竞争激烈时)、ReentrantLock | Java的AtomicInteger、SpinLock(自定义实现) |
| 优点 | 节省CPU资源,适合高竞争场景 | 无上下文切换,延迟极低 |
| 缺点 | 线程切换开销大,响应延迟高 | 自旋过久会浪费CPU,可能饥饿 |
| 死锁风险 | 可能死锁(需超时或中断机制) | 无死锁(但可能活锁) |
关键细节说明
-
挂起等待锁(阻塞锁)
-
适用场景:锁竞争激烈或临界区执行时间较长(如数据库事务)。
-
优化建议:
-
使用
ReentrantLock替代synchronized(支持超时和中断)。 -
设置合理的锁超时时间(避免死锁)。
-
-
-
自旋锁
-
适用场景:锁持有时间极短(如计数器递增)。
-
优化建议:
-
限制自旋次数(如JVM的
-XX:PreBlockSpin参数)。 -
升级为自适应自旋锁(根据历史自旋时间动态调整)。
-
-
选择建议
-
优先用自旋锁:
-
临界区代码执行时间 < CPU上下文切换时间(通常约1μs)。
-
例如:
AtomicInteger的CAS操作。
-
-
优先用挂起等待锁:
-
临界区代码执行时间 > 自旋消耗的CPU时间。
-
例如:同步访问数据库连接池。
-
4.普通互斥锁vs读写锁
普通互斥锁:锁之间完全互斥,同一时间只能有一个线程持有锁,分为‘加锁’和‘解锁’两个过程。synchronized就是经典的普通互斥锁。
读写锁:应对某些读多写少的情况,分为“读锁”和“写锁”两种,其中“读锁”和“读锁”之间不互斥,支持了多个线程同时读取的情况,减少了锁冲突的情况。
读写锁互斥规则详解
-
读锁 vs 读锁
-
不互斥:多个线程可同时持有读锁(共享)。
-
示例:100个线程可同时读取缓存数据。
-
-
读锁 vs 写锁
-
完全互斥:
-
已有读锁时,写锁请求被阻塞(直到所有读锁释放)。
-
已有写锁时,读锁请求被阻塞(直到写锁释放)。
-
-
-
写锁 vs 写锁
-
完全互斥:同一时刻只允许一个写锁存在。
-
普通互斥锁 vs 读写锁对比
| 特性 | 普通互斥锁(Mutex Lock) | 读写锁(Read-Write Lock) |
|---|---|---|
| 锁模式 | 排他锁(Exclusive Lock) | 读锁(共享锁) + 写锁(排他锁) |
| 并发性 | 完全互斥,同一时刻只有一个线程能持有锁 | 读锁可共享(允许多线程同时读),写锁互斥 |
| 适用场景 | 写操作频繁或读写操作时间相近 | 读多写少(如缓存、配置读取) |
| 性能 | 高竞争下性能差 | 读并发高,写操作会阻塞所有读/写 |
| 公平性 | 支持公平/非公平(如ReentrantLock) | 通常支持公平/非公平(如ReentrantReadWriteLock) |
| 锁降级 | 不支持 | 支持(持有写锁的线程可以获取读锁,再释放写锁) |
| 锁升级 | 不支持 | 不支持(读锁不能直接升级为写锁,易死锁) |
| 实现复杂度 | 简单 | 较复杂(需维护读/写状态) |
| 典型实现 | Java: synchronized、ReentrantLock | Java: ReentrantReadWriteLock |
| 优点 | 实现简单,严格保证一致性 | 读操作高并发,适合读多写少场景 |
| 缺点 | 读写均互斥,并发性差 | 写操作饥饿风险(长期有读锁时写锁无法获取) |
5.可重入锁vs不可重入锁
可重入锁:允许同一个线程多次获取一把锁。
不可重入锁:不允许同一个线程多次获取同一把锁。
| 特性 | 可重入锁 | 不可重入锁 |
|---|---|---|
| 递归调用支持 | ✅ 同一线程可重复获取同一把锁(计数器递增) | ❌ 同一线程重复获取会死锁 |
| 死锁风险 | 低(允许嵌套加锁) | 高(递归调用或嵌套加锁直接死锁) |
| 实现复杂度 | 较高(需维护持有线程和重入次数) | 简单(仅检查锁是否被占用) |
| 典型应用场景 | 递归函数、同步方法调用其他同步方法 | 简单临界区保护(无嵌套调用场景) |
| 性能开销 | 略高(需维护重入状态) | 较低(无状态跟踪) |
| 锁释放要求 | 必须释放与获取次数匹配(如加锁3次需解锁3次) | 只需释放1次 |
| 公平性支持 | 通常支持(如ReentrantLock(true)) | 通常不支持 |
| 中断响应 | 支持(lockInterruptibly()) | 一般不支持 |
| 实现示例 | Java: synchronized、ReentrantLockC++: std::recursive_mutex | Java: 自定义简单锁 C: pthread_mutex(默认不可重入) |
| 适用性 | 通用场景(尤其是复杂同步逻辑) | 极简场景(无嵌套/递归) |
选择建议
-
用可重入锁:
-
存在方法嵌套/递归调用同步代码。
-
使用类库提供的锁(如Java的
synchronized)。
-
-
用不可重入锁:
-
绝对无嵌套的简单临界区(性能敏感场景)。
-
需要极轻量级同步原语(如自定义自旋锁)。
-
6.公平锁vs不公平锁
公平锁:线程采用“先来后到”的思想来依次获取锁。
不公平锁:线程采用“概率相等”的思想来获取锁。
1) 公平锁和不公平锁的对比
| 特性 | 公平锁 (Fair Lock) | 非公平锁 (Non-Fair Lock) |
|---|---|---|
| 获取锁顺序 | 严格按照线程请求顺序(先到先得) | 允许插队(新线程可能直接抢到锁) |
| 吞吐量 | 较低(线程切换频繁) | 较高(减少线程切换) |
| 线程饥饿 | 不会发生(保证每个线程有机会执行) | 可能发生(某些线程长期抢不到锁) |
| 实现复杂度 | 较高(需维护等待队列) | 较低(直接竞争) |
| 适用场景 | 要求严格公平性(如订单处理、金融交易) | 高并发场景,追求性能(如缓存、计数器) |
| 锁获取策略 | 检查是否有等待更久的线程,有则排队 | 直接尝试获取锁,失败才进入队列 |
| 典型实现 | ReentrantLock(true) | ReentrantLock(false)(默认)、synchronized |
| 响应时间 | 较稳定(按序执行) | 波动较大(可能某些线程更快) |
| CPU利用率 | 较低(线程频繁挂起/唤醒) | 较高(减少上下文切换) |
| 锁竞争激烈时 | 所有线程按序执行,但吞吐量下降 | 可能某些线程一直抢到锁,其他线程等待更久 |
2)选择建议
| 场景 | 推荐锁类型 | 原因 |
|---|---|---|
| 需要严格顺序(如交易系统) | 公平锁 | 避免某些请求被无限延迟 |
| 高并发、低延迟(如缓存) | 非公平锁 | 减少线程切换,提高吞吐量 |
| 线程执行时间差异大 | 公平锁 | 防止短任务“饿死”长任务 |
| 锁竞争不激烈 | 非公平锁 | 插队概率低,性能接近公平锁但开销更小 |
7.锁升级
锁升级是多线程并发控制中的一种优化策略,指JVM根据竞争情况动态调整锁的级别,从低开销锁逐步升级为高开销锁的过程。
无锁 → 偏向锁 → 轻量级锁 → 重量级锁
| 锁级别 | 升级时机 | 特点 | 适用场景 |
|---|---|---|---|
| 无锁 | 无 | 对象未被任何线程锁定 | 新建对象 |
| 偏向锁 | 代码进入synchronized代码块 =>偏向锁 | 仅记录线程ID,无实际同步,只是一个标记,不是锁 | 单线程访问 |
| 轻量级锁 | 其他线程尝试获取这个锁 =>轻量级锁 | CAS自旋尝试获取锁 | 低竞争多线程 |
| 重量级锁 | JVM发现,当前竞争锁的情况非常激烈 =>重量级锁 | 操作系统互斥量实现 | 高竞争场景 |
总的来说,锁升级是懒汉模式思想的一种体现,旨在减少开销。锁升级只升不降,不可以再转化回去。
8.锁优化
锁优化是提升多线程程序性能的关键手段,JIT编译器通过逃逸分析移除不必要的锁。旨在减少锁的开销。
9.锁的粗化
锁粗化是JVM针对同步代码的一种重要优化技术,它通过合并相邻的同步块来减少不必要的锁获取/释放操作,从而提升程序执行效率。
| 粒度级别 | 含义 | |||
|---|---|---|---|---|
| 粗粒度 | 在一把锁之间代码更多 | |||
| 细粒度 | 在一把锁之间代码更少 |
锁的粗化实际上就是通过将多把锁合并为一把锁来减少频繁上锁、解锁的开销,使得一把锁之间的代码变得更多。
10.synchronized
| 锁的类型 | synchronized |
|---|---|
| 悲观锁还是乐观锁? | 自适应 |
| 重量级锁还是轻量级锁? | 自适应 |
| 挂起等待锁还是自旋锁? | 自适应 |
| 普通互斥锁还是读写锁? | 普通互斥锁 |
| 可重入锁还是不可重入锁? | 可重入锁 |
| 公平锁还是不公平锁? | 公平锁 |
11.reentrantlock和synchronized的对比
ReentrantLock 是 Java 并发包(java.util.concurrent.locks)中提供的可重入互斥锁实现,它比传统的 synchronized 关键字提供更灵活的锁操作。
以下是reentrantlock和synchronized的五点区别:
| 区别 | reentrantlock | synchronized |
|---|---|---|
| 实现方式 | Java标准库中的类,由JDK实现 | 关键字,由JVM实现,JVM基于C++实现 |
| 加锁方法 | 通过lock()和unlock()方法加锁和解锁,有可能因为忘记解锁而触发线程安全问题 | 通过代码块控制加锁、解锁 |
| trylock()方法 | 具备trylock()方法,尝试获取锁而不会无限期阻塞 | 不具备 |
| 公平锁与非公平锁 | 默认是非公平锁,但是也可以实现公平锁 | 非公平锁 |
| 等待通知机制 | 等待通知机制是condition类,比synchronized的wait、notify功能更为强大 | wait、notify |
相关文章:
多线程编程中的锁策略
目录 1.悲观锁vs乐观锁 关键总结 悲观锁: 乐观锁: 选择建议 用 悲观锁 当: 用 乐观锁 当: 2.重量级锁vs轻量级锁 选择建议 用 轻量级锁: 用 重量级锁: 3.挂起等待锁vs自旋锁 关键细节说明 选择…...
win10 笔记本电脑安装 pytorch+cuda+gpu 大模型开发环境过程记录
win10 笔记本电脑安装 pytorchcudagpu 大模型开发环境过程记录 文章部分内容参考 deepseek。 以下使用命令行工具 mingw64。 安装 Anaconda 安装位置: /c/DEVPACK/Anaconda3 然后安装 Python 3.10.16 (略) $ conda create -n pytorch_…...
Layout Inspector平替跨平台布局分析器のAppium Inspector
引言 因为我有一个api为26的设备,因为 Layout Inspector 无法在 API 26 以下设备上使用,并且现在AS的 Hierarchy Viewer 和Android Device Monitor 均已经在SDK中剔除,故想再搜一个pc版的布局查看器,发现Appium Inspector学习成本…...
基于sklearn实现文本摘要思考
和各位小伙伴分享一下使用sklearn进行文本摘要的思考。 第一版本 原理 提取式文本摘要的基本原理是: 将文本分割成句子 计算每个句子的重要性(权重) 选择权重最高的几个句子组成摘要 常用的句子权重计算方法: TF-IDF:基于词频-逆文档频…...
常见NLP指标PPL,F1,Rouge-L,Accuracy (CLS),Accuracy (EM)总结
常见NLP指标PPL,F1,Rouge-L总结 1.PPL 2.F1 3.Rouge-L 4.Accuracy (CLS) 5.Accuracy (EM)...
Redis数据结构之ZSet
目录 1.概述2.常见操作2.1 ZADD2.2 ZRANGE2.3 ZREVRANGE2.4 ZRANGEBYSCORE2.5 ZSCORE2.6 ZCARD2.6 ZREM2.7 ZINCRBY2.8 ZCOUNT2.9 ZMPOP2.10 ZRANK2.11 ZREVRANK 3.总结 1.概述 ZSet和Set一样也是String类型元素的集合,且不允许重复的成员,不同的是ZSet…...
使用binance-connector库获取Binance全市场的币种价格,然后选择一个币种进行下单
一个完整的示例,展示如何使用 api 获取Binance全市场的币种价格,然后选择一个最便宜的币种进行下单操作 代码经过修改,亲测可用,目前只可用于现货,合约的待开发 获取市场价格:使用client.ticker_price()获取所有交易对的当前价格 账户检查:获取账户余额,确保有足够的资…...
磁盘分析工具合集:告别C盘焦虑!
今天李师傅带大家盘点五款硬盘空间分析利器,帮你精准定位那些"吃空间"的元凶,让C盘告别臃肿烦恼! 一、WizTree 这款NTFS磁盘的"透视眼"堪称效率典范。它通过直接读取硬盘主文件表(MFT)实现秒级扫描,1TB机械…...
20250405在荣品的PRO-RK3566开发板使用Rockchip原厂的buildroot系统来适配gmac1
【暂时还没有解决让PRO-RK3566的eth0/gmac1开机就启动】 PRO-RK3566作为iperf服务器: rootrk3566-buildroot:/# ifconfig rootrk3566-buildroot:/# ifconfig -a rootrk3566-buildroot:/# ifconfig eth0 up rootrk3566-buildroot:/# ifconfig rootrk3566-buildroot:/…...
Spring / Spring Boot 的@MapperScan 和 @Repository
MapperScan 和 Repository 是两个与数据访问层相关的注解,它们在功能上有一定的联系,但也有明显的区别。 一、相同点 1. 都与数据访问层相关 MapperScan:用于扫描 MyBatis 的 Mapper 接口。MyBatis 是一个流行的持久层框架,Mapp…...
SDL中SDL_AudioSpec结构体参数
文章目录 ✅ SDL_AudioSpec 结构体定义📌 每个字段详细解释 设置依据1. freq:采样频率(Sample Rate)2. format:采样格式(Sample Format)3. channels:通道数(Channels&am…...
每日一题(小白)模拟娱乐篇14
直接理解题意,一分钟扩散一次,那么2020分钟也就是需要循环2020次,然后加入扩散后的条件,每一个次扩散使方格子的总量1(只要有一个点扩散就无需看其他的点),若干次循环过后总数之和即所有黑色格子…...
使用 Python 爬取并打印双色球近期 5 场开奖数据
使用 Python 爬取并打印双色球近期 5 场开奖数据 前期准备安装所需库 完整代码代码解析 1. 导入必要的库2. 定义函数 get_recent_five_ssq 3. 设置请求的 URL 和 Headers 4. 发送请求并处理响应5. 解析 HTML 内容6. 提取并打印数据7. 错误处理 首先看下运行的效果图:…...
再见VS Code!Google IDE 正颠覆传统开发体验
云端开发的革命:Google Project IDX 如何颠覆传统开发体验 在软件开发领域,Google 最新推出的 Project IDX 绝非仅仅是另一个“基于浏览器的 VS Code”——它是一次真正的范式转变。与 VS Code、Cursor 等传统工具不同,IDX 是一个完全云原生的…...
Java Web从入门到精通:全面探索与实战(一)
目录 引言:开启 Java Web 之旅 一、Java Web 基础概念大揭秘 1.1 什么是 Java Web 1.2 Java Web 的优势剖析 1.3 Java Web 相关核心概念详解 二、搭建 Java Web 开发环境:步步为营 2.1 所需软件大盘点 2.2 软件安装与配置全流程 三…...
AI+自动化测试:如何让测试编写效率提升10倍?
文章目录 摘要传统自动化测试的痛点编写测试用例太费时间测试覆盖率难以保证UI 测试维护成本高 AI 如何优化自动化测试?AI 生成单元测试:减少重复工作,提高覆盖率传统方法 VS AI 方法 使用 AI 生成 Python 单元测试自动补全边界情况传统方法 …...
软件工程面试题(三十)
将ISO8859-1字符串转成GB2312编码,语句为? String snew String(text.getBytes(“iso8859-1”),”gb2312”). 说出你用过的J2EE标准的WEB框架和他们之间的比较? 答:用过的J2EE标准主要有:JSP&Servlet、JDBC、JNDI…...
01-STM32(介绍、工具准备、新建工程)p1-4
文章目录 工具准备和介绍硬件设备stm32简介和arm简介stm32简介STM32命名规则STM32选型STM32F103C8T6最小系统板引脚定义STM32启动配置STM32最小系统电路ARM简介 软件安装注册器件支持包安装ST-LINK驱动安装USB转串口驱动 新建工程创建stm32工程STM32工程编译和下载型号分类及缩…...
Win10定时任务计划无法显示要执行的EXE任务程序界面,问题解决办法
用C#开发的一款WINFORM程序,在电脑测试一切顺利,运行结果正确。但用电脑的定时任务执行时,程序界面不显示,重启电脑、各种试都不行,最终问题解决。 解决办法: 要选“只在用户登陆时运行”,才能执…...
STM32CubeMX-H7-12-IIC读写MPU6050模块(中)-MPU6050模块详解以及软件IIC驱动
前言 上一篇我们已经完成对IIC代码基本框架的编写,以及获取MPU6050的ID,接下来我们逐一分析这个模块的功能,并用IIC驱动 建议看完上一篇再来看这篇 MPU6050寄存器介绍 1.电源管理寄存器(PWR_MGMT_1,地址:0…...
基于Go语言实现一个网络聊天室(连接Redis版)
基于Go语言和Redis的实时聊天室项目详解 项目概述 在这个项目中,我们实现了一个基于Go语言和Redis的实时聊天室系统。该系统允许用户通过客户端连接到服务器,进行实时聊天,并且支持以下功能: 用户网名注册和验证消息广播和接收…...
深入解析 RocketMQ 中的 BrokerOuterAPI 组件
在 RocketMQ 这一高性能分布式消息队列系统中,BrokerOuterAPI 组件犹如一座桥梁,连接着 Broker 与外部世界,在系统的运行、管理以及与其他组件交互过程中发挥着极为关键的作用。本文将深入探讨 BrokerOuterAPI 组件的内部机制、核心功能以及其…...
make_01_Program_06_:: 是什么功能
在 Makefile 中,:: 是一种特殊的分隔符,用于创建多重规则(multiple rules)。当您使用 :: 定义目标时,您可以为同一个目标指定多个命令或多个依赖关系。每个命令将在构建目标时按顺序执行,不会影响其他命令的…...
springboot2.7.x整合nacos+seata
1、nacos及seata下载地址 Nacos Server 下载 | Nacos 官网 Seata Java Download | Apache Seata 这里的seata版本用2.1.0版本。 2、启动nacos D:\本地-seata-nacos\nacos-server\bin>startup.cmd -m standalone 3、修改seata的conf下的application的内容 这里的数据库…...
为 IDEA 设置管理员权限
IDEA 安装目录 兼容性选择管理员身份运行程序 之后 IDEA 中的操作(包括终端中的操作)都是管理员权限的了...
Apache Doris 2.1.9 版本正式发布
亲爱的社区小伙伴们,Apache Doris 2.1.9 版本已正式发布。2.1.9 版本对湖仓一体、倒排索引、半结构化数据类型、查询优化器、执行引擎、存储管理进行了若干改进优化。欢迎大家下载使用。 官网下载:https://doris.apache.org/download GitHub 下载&…...
单片机学习笔记8.定时器
IAP15W4K58S4定时/计数器结构工作原理 定时器工作方式控制寄存器TMOD 不能进行位寻址,只能对整个寄存器进行赋值 寄存器地址D7D6D5D4D3D2D1D0复位值TMOD89HGATEC/(T低电平有效)M1M0GATEC/(T低电平有效)M1M000000000B D0-D3为T0控制,D4-D7为T1控制 GAT…...
vue3实现markdown预览和编辑
Markdown作为一种轻量级标记语言,已经成为开发者编写文档的首选工具之一。在Vue3项目中集成Markdown编辑和预览功能可以极大地提升内容管理体验。本文将介绍如何使用Vditor这一强大的开源Markdown编辑器在Vue3项目中实现这一功能。 一、Vditor简介 Vditor是一款浏…...
高并发秒杀系统接入层如何设计
博主介绍:✌全网粉丝5W,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验…...
C++异常处理 throw try catch
C 异常处理概述 C 异常处理机制提供了一种在程序运行时捕获错误或异常情况的方式。异常处理的目的是使得程序在遇到错误时能够优雅地终止或恢复,并防止程序出现崩溃。C 使用 try, throw, 和 catch 关键字来实现异常处理。 异常处理的基本结构: throw: …...
