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

【多线程】门栓/闭锁(Latch/CountDownLatch)

【多线程】门栓/闭锁(Latch/CountDownLatch)

本文来自于我关于多线程的系列文章。欢迎阅读、点评与交流
1.【多线程】互斥锁(Mutex)是什么?
2.【多线程】临界区(Critical Section)是什么?
3.【多线程】计算机领域中的各种锁
4.【多线程】信号量(Semaphore)是什么?
5.【多线程】信号量(Semaphore)常见的应用场景
6.【多线程】条件变量(Condition Variable)是什么?
7.【多线程】监视器(Monitor)是什么?
8.【多线程】什么是原子操作(Atomic Operation)?
9.【多线程】竞态条件(race condition)是什么?
10.【多线程】无锁数据结构(Lock-Free Data Structures)是什么?
11.【多线程】线程休眠(Thread Sleep)的底层实现
12.【多线程】多线程的底层实现
13.【多线程】读写锁(Read-Write Lock)是什么?
14.【多线程】死锁(deadlock)
15.【多线程】线程池(Thread Pool)
16.【多线程】忙等待/自旋(Busy Waiting/Spinning)
17.【多线程】阻塞等待(Blocking Wait)(以Java为例)
18.【多线程】阻塞等待(Blocking Wait)(以C++为例)
19.【多线程】屏障(Barrier)
20.【多线程】闭锁(Latch/CountDownLatch)
21.【多线程硬件机制】总线锁(Bus Lock)是什么?
22.【多线程硬件机制】缓存锁(Cache Lock)是什么?

1. 核心概念

门栓/闭锁(Latch/CountDownLatch)是一种同步工具类,它允许一个或多个线程等待,直到在其他线程中执行的一系列操作完成。(相比起闭锁(CountDownLatch),我觉得门栓(Latch)翻译更好,更形象)

你可以把它想象成一扇门闩(Latch):

  • 在门闩关闭时,任何线程都无法通过。
  • 当门闩打开时,所有线程都可以通过。
  • 门闩一旦打开,就永远保持打开状态,不能再关闭。

在并发编程中,闭锁用于确保某些活动直到其他活动完成后才继续执行。

2. 核心工作原理

闭锁内部维护着一个计数器。这个计数器的初始值在创建时被设定,代表需要等待完成的“事件”数量。

  • 计数递减:当一个线程完成了一个事件,它就调用 countDown() 方法,这会使计数器减1
  • 等待:其他需要等待所有这些事件完成的线程(例如主线程),会调用 await() 方法。
  • 阻塞与释放
    • 调用 await() 的线程会被阻塞(即暂停执行),直到计数器的值变为 0
    • 当计数器减到 0 时,所有在 await() 上等待的线程都会被唤醒并继续执行。

关键特性:

  • 一次性:闭锁的状态是不可逆的。一旦计数器到达 0,它就永远保持在 0 的状态。所有后续调用 await() 的线程都会立即通过,不会再被阻塞。
  • 协作:它实现了线程之间的协作,而不是互斥(像锁那样)。

3. 主要用途和场景

闭锁在以下场景中非常有用:

  1. 确保服务在依赖项就绪后才开始
    例如,一个主服务需要等待其他几个基础服务(如数据库连接池、网络服务、配置文件加载等)全部初始化完成后才能启动。每个基础服务启动完毕后就调用 countDown(),主服务在 await() 处等待。

  2. 等待所有线程完成初始化任务
    在游戏服务器中,可能需要等待所有玩家都加载完地图和数据后再开始游戏。

  3. 最大并发测试
    创建一个初始值为 N 的闭锁。启动 N 个线程,每个线程都在开始执行测试任务前调用 await()。主线程在启动所有线程后调用 countDown(),由于初始值为1,所以这会导致所有等待的线程在同一时刻开始执行,从而模拟出最大的并发压力。

  4. 计算任务的分解与汇总
    将一个大型计算任务分解为多个子任务,每个子任务完成后调用 countDown()。一个汇总线程等待所有子任务完成后,再进行结果汇总。

4. 代码示例(Java)

在 Java 中,最常用的闭锁实现是 java.util.concurrent.CountDownLatch

场景:主线程需要等待三个工作线程都完成各自的任务后,才能继续执行。

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;public class CountDownLatchDemo {public static void main(String[] args) throws InterruptedException {// 1. 创建一个初始计数器为 3 的闭锁CountDownLatch latch = new CountDownLatch(3);// 2. 创建并启动三个工作线程for (int i = 1; i <= 3; i++) {new Thread(new Worker(latch), "Worker-" + i).start();}System.out.println("主线程正在等待所有工作线程完成...");// 3. 主线程在此等待,直到计数器变为0latch.await();// 4. 所有工作线程都已完成,主线程继续执行System.out.println("所有工作线程都已完成!主线程继续执行。");}static class Worker implements Runnable {private final CountDownLatch latch;public Worker(CountDownLatch latch) {this.latch = latch;}@Overridepublic void run() {try {// 模拟工作线程正在执行任务System.out.println(Thread.currentThread().getName() + " 正在执行任务...");TimeUnit.SECONDS.sleep((long) (Math.random() * 3 + 1)); // 模拟耗时System.out.println(Thread.currentThread().getName() + " 任务完成!");} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {// 5. 任务完成后,调用 countDown() 将计数器减1// 这个调用必须放在 finally 中,确保无论如何都会执行latch.countDown();}}}
}

可能的输出:

主线程正在等待所有工作线程完成...
Worker-1 正在执行任务...
Worker-2 正在执行任务...
Worker-3 正在执行任务...
Worker-1 任务完成!
Worker-3 任务完成!
Worker-2 任务完成!
所有工作线程都已完成!主线程继续执行。

5. 与其他同步工具的比较

  • CyclicBarrier 比较

    • 闭锁:用于等待事件,是一次性的。一个线程 countDown(),另一个线程 await()
    • 循环屏障:用于线程彼此等待,是可重用的。所有线程都必须在屏障处调用 await() 才能继续。
  • Future / CompletableFuture 比较

    • Future 更侧重于表示一个异步计算的结果
    • 闭锁更侧重于一种**“就绪信号”**,它本身不携带计算结果,只关心“完成”这个状态。

总结

闭锁是一个简单而强大的线程同步工具,它通过一个计数器来实现**“等待-通知”的机制。其核心思想是让一个或多个线程等待,直到一组操作在其他线程中执行完成。它的一次性**特性使其特别适用于那种“万事俱备,只欠东风”的并发场景。

http://www.dtcms.com/a/478923.html

相关文章:

  • [1-02-02].[第01章:HTML + CSS
  • 手机必备网站软件技术专科生的出路
  • 网站空间续费一年多少钱怎么弄推广广告
  • 一个做任务的网站如何绑定域名wordpress
  • 当ubuntu 系统的IP地址修改之后,gitlab服务应该如何修改?
  • 怎么做自己的公司网站本地服务器 wordpress
  • 网站制作 优帮云做淘宝客网站需要做后台吗
  • xsync.sh分发脚本和命令执行脚本
  • 深圳高端网站设计公司大连网站建设免费
  • mysql DATE_SUB函数 对日期或时间进行减法运算
  • 企业微信网站开发公司网易企业邮箱怎么找回密码
  • 力扣热题100p128最长连续序列
  • 【LeetCode热题100(42/100)】将有序数组转换为二叉搜索树
  • google网站建设网站开发答辩ppt
  • 超越CNN:GCN如何重塑图像处理
  • A100云服务器租赁:边缘计算时代的算力新形态
  • 建设项目环评验收网站做网站都需要年服务费吗
  • js中 btoa 方法 和 atob方法介绍
  • 做网络写手 哪个网站比较好亚马逊deal网站怎么做
  • css布局的几种方式
  • 前端数值运算精度丢失问题及解决方案
  • 免费建站软件有哪些苏州建行网站首页
  • 极海APM32F107V6 移植FreeRTOS+CMSIS-RTOS V2
  • Centos Stream 8 搭建Cas Server
  • 营销型网站建设优化汽车电商网站建设
  • 网站建设中最基本的决策南昌网站建设和推广
  • 网页设计网站如何添加链接家庭网站建设
  • ModuleNotFoundError: No module named ‘conda_token‘
  • 长春哪家做网站做的好网站建设员是做什么的
  • Milvus部署在T4 GPU上,Dify检索性能可以提升多少?