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

Semaphore、CountDownLatch、ReentrantLock使用场景简单说说

目录
  • Semaphore、CountDownLatch、ReentrantLock使用场景简单说说
    • 1. Semaphore(信号量)
    • 2. CountDownLatch(倒计时门闩)
    • 3. ReentrantLock(可重入锁)
    • 对比总结
    • 简单记忆
  • 三个并发工具的简单示例
    • 1. Semaphore 示例 - 停车场系统
    • 2. CountDownLatch 示例 - 比赛准备
    • 3. ReentrantLock 示例 - 银行取款
    • 一句话总结

Semaphore、CountDownLatch、ReentrantLock使用场景简单说说

1. Semaphore(信号量)

核心思想:控制并发访问资源的线程数量(资源池)

典型场景

// 1. 数据库连接池(控制最大连接数)
Semaphore semaphore = new Semaphore(10); // 最多10个并发连接// 2. 限流(接口限流、流量控制)
Semaphore rateLimiter = new Semaphore(100); // QPS限制为100// 3. 停车场系统(有限停车位)
Semaphore parkingSpots = new Semaphore(50); // 50个车位

关键点acquire()获取许可,release()释放许可,可指定许可数量。

2. CountDownLatch(倒计时门闩)

核心思想:让一个或多个线程等待其他线程完成操作

典型场景

// 1. 主线程等待所有子线程初始化完成
CountDownLatch latch = new CountDownLatch(5);
// 每个子线程完成时调用 latch.countDown()
// 主线程调用 latch.await() 等待// 2. 并行计算,汇总结果
// 3. 模拟并发测试(同时发起请求)
// 4. 游戏等待所有玩家准备就绪

关键点:一次性使用,计数减到0后所有等待线程被唤醒。

3. ReentrantLock(可重入锁)

核心思想:替代synchronized的显式锁,提供更灵活的锁控制

典型场景

// 1. 需要尝试获取锁(避免死锁)
if (lock.tryLock(3, TimeUnit.SECONDS)) {try {// 临界区} finally {lock.unlock();}
}// 2. 公平锁需求(按申请顺序获取锁)
ReentrantLock fairLock = new ReentrantLock(true);// 3. 需要条件变量的复杂同步
Condition condition = lock.newCondition();
condition.await(); // 等待条件
condition.signal(); // 唤醒// 4. 可中断的锁获取
lock.lockInterruptibly();

对比总结

工具 核心用途 是否可重用 关键特性
Semaphore 控制资源访问并发数 许可机制,可增可减
CountDownLatch 等待其他线程完成 否(一次性) 倒计时,不可重置
ReentrantLock 替代synchronized的互斥锁 可重入、可中断、公平/非公平、条件变量

简单记忆

  • Semaphore流量控制(多少辆车能上高速)
    • 核心思想:控制并发访问资源的线程数量(资源池)
  • CountDownLatch起跑线(等所有运动员就位)
    • 核心思想:让一个或多个线程等待其他线程完成操作
  • ReentrantLock加强版synchronized(需要更精细控制时用)
    • 核心思想:替代synchronized的显式锁,提供更灵活的锁控制

根据具体需求选择:

  • 需要限流/资源池 → Semaphore
  • 需要等待多个任务完成 → CountDownLatch
  • 需要灵活的锁控制 → ReentrantLock

三个并发工具的简单示例

1. Semaphore 示例 - 停车场系统

import java.util.concurrent.Semaphore;public class ParkingLot {public static void main(String[] args) {Semaphore parkingSpots = new Semaphore(3); // 只有3个停车位// 5辆车尝试停车for (int i = 1; i <= 5; i++) {new Thread(() -> {try {parkingSpots.acquire(); // 获取停车位System.out.println(Thread.currentThread().getName() + " 停入车位");Thread.sleep(2000); // 停车2秒System.out.println(Thread.currentThread().getName() + " 离开车位");parkingSpots.release(); // 释放停车位} catch (InterruptedException e) {e.printStackTrace();}}, "车辆" + i).start();}}
}

输出结果

车辆1 停入车位
车辆2 停入车位
车辆3 停入车位
(等待...)
车辆1 离开车位
车辆4 停入车位
车辆2 离开车位
车辆5 停入车位
...

2. CountDownLatch 示例 - 比赛准备

import java.util.concurrent.CountDownLatch;public class Race {public static void main(String[] args) throws InterruptedException {CountDownLatch readySignal = new CountDownLatch(3); // 3个运动员System.out.println("裁判:各就各位!");// 3个运动员线程for (int i = 1; i <= 3; i++) {new Thread(() -> {System.out.println(Thread.currentThread().getName() + " 准备就绪");readySignal.countDown(); // 计数减1}, "运动员" + i).start();}readySignal.await(); // 裁判等待所有运动员就位System.out.println("裁判:预备...跑!");}
}

输出结果

裁判:各就各位!
运动员1 准备就绪
运动员2 准备就绪
运动员3 准备就绪
裁判:预备...跑!

3. ReentrantLock 示例 - 银行取款

import java.util.concurrent.locks.ReentrantLock;public class BankAccount {private int balance = 1000;private ReentrantLock lock = new ReentrantLock();// 取款操作public boolean withdraw(int amount) {lock.lock(); // 手动加锁try {if (balance >= amount) {Thread.sleep(100); // 模拟处理时间balance -= amount;System.out.println(Thread.currentThread().getName() + " 取款" + amount + ",余额:" + balance);return true;}return false;} catch (InterruptedException e) {e.printStackTrace();return false;} finally {lock.unlock(); // 必须在finally中解锁!}}public static void main(String[] args) {BankAccount account = new BankAccount();// 两个人同时取款new Thread(() -> account.withdraw(800), "张三").start();new Thread(() -> account.withdraw(800), "李四").start();}
}

输出结果

张三 取款800,余额:200
李四 取款失败(余额不足)

注意:如果没有锁,可能两人都取款成功,导致余额为负数!

一句话总结

// Semaphore:控制数量(最多N个同时访问)
Semaphore sem = new Semaphore(5); // 最多5个// CountDownLatch:等待完成(等N个完成后继续)
CountDownLatch latch = new CountDownLatch(3); // 等3个// ReentrantLock:替代synchronized(手动加锁解锁)
lock.lock(); // 加锁
lock.unlock(); // 解锁
http://www.jsqmd.com/news/69320/

相关文章:

  • 独占锁和共享锁唤醒机制
  • 个人学习---25.12.9
  • 大模型完整架构
  • iOS 知识点 - 一篇文章带你串通「操作系统 内存模型 文件系统」
  • 2025年12月天津金蝶软件代理商最新推荐:天津鹏越软件,金蝶云星空、金蝶云星晨、金蝶云星翰、助力企业高效落地ERP系统与全场景管理升级
  • 102302114_比山布努尔兰_作业4
  • 2025年12月济南艺考画室最新推荐:济南大道画室,济南艺考画室、济南画室哪家好、济南画室推荐、山东美术艺考培训、山东画室个性化教学新标杆
  • 记一次磁盘占满的问题
  • Redis提供的原子性命令
  • 多业态连锁环境管理系统:AI + 机器人闭环,坪效提升 16%
  • 2025年12月室内水上乐园厂家推荐:山东汇川,儿童水上乐园、大型水上乐园、主题水上乐园、室外水上乐园、恒温泳池、室 泳池、全场景适配新标杆
  • 2025雅思培训班怎么选?这5家高性价比机构帮你高效提分
  • 2025年12月水上乐园设备厂家最新推荐:昊至泉充气水上乐园设备、室内水上乐园设备、户外水上乐园设备、大型水上乐园设备、漂流河水上乐园设备、打造安全创新个性化水上娱乐新标准
  • 实用指南:「腾讯云NoSQL」技术之向量数据库篇:自研分布式向量数据库,实现毫秒级时序一致备份的挑战和实践
  • py-lambda-map-list随笔
  • 杂题选记
  • 2025年12月铝材厂家推荐榜:廊坊国美铝业,工业铝材、门窗铝材、3C铝材、通用铝材、多领域铝材定制与绿色生产标杆
  • Qt 文本转语言(QTextToSpeech类)详解 - 实践
  • AWS发布网络扫描指南:构建更安全云环境的守则
  • # 题解#洛谷P2880 Balanced Lineup #ST表#
  • 2025年12月包头保洁公司最新推荐:信达家政,包头保洁开荒、包头高空清洗保洁、包头保姆公司、包头保姆家政、包头保姆月嫂、包头保姆护工、服务品质新标准
  • 机器视觉测量与建模
  • 2025最值得报的雅思封闭班:高性价比/冲高分/打基础三类优选清单
  • 为什么会诞生流形的概念?
  • [Java EE] 多线程 -- 初阶(1) - 详解
  • 2025年12月丝杆升降机标杆厂家最新推荐:德州德特机械,螺旋升降机、sjb螺旋升降机、zimm螺旋升降机、SJA螺旋升降机、联动丝杆升降机、螺旋丝杆升降机、专注精密传动新标准
  • AQS与CAS深度讲解
  • 2025年唐老狮权威解读:游戏开发课的体系化构建优势
  • 2025年12月注浆工程厂家推荐:安徽林固,道路注浆、空鼓注浆、公路注浆、路基注浆、地基注浆、厂房注浆、地坪注浆、矿山注浆、多场景注浆解决方案服务商
  • PROFILE