当前位置:首页 > 科技  > 软件

并发协调神器CountDownLatch和CyclicBarrier

来源: 责编: 时间:2024-04-02 17:17:50 270观看
导读1.引言从Java的最初版本开始,就可以利用Java来进行多线程编程。正因为Java从最早的版本就支持多线程编程,程序员们才能够利用Java强大的多线程机制来实现并发任务的执行。然而,多线程编程虽然强大,却也带来了一系列潜在的

QHW28资讯网——每日最新资讯28at.com

1.引言

从Java的最初版本开始,就可以利用Java来进行多线程编程。正因为Java从最早的版本就支持多线程编程,程序员们才能够利用Java强大的多线程机制来实现并发任务的执行。然而,多线程编程虽然强大,却也带来了一系列潜在的问题和挑战。QHW28资讯网——每日最新资讯28at.com

假设有一个共享的咖啡机,多个同事在办公室中使用它来冲泡咖啡。这里就存在着典型的多线程问题:QHW28资讯网——每日最新资讯28at.com

  • 竞态条件(Race Condition):多个同事同时按下冲泡按钮,如果没有适当的控制和同步机制,可能会导致咖啡机出现异常行为,比如一次性冲出过多的咖啡或者没有冲出咖啡。
  • 死锁(Deadlock):例如,如果两个同事分别占用了添加水和放置咖啡粉的步骤,但互相等待对方完成,那么咖啡机就无法继续工作了。
  • 数据同步(Data Synchronization):确保每个同事知道何时该添加水、何时该放置咖啡粉,以及何时可以开始冲泡,从而避免出现混乱或资源争夺的情况。

2.并发引出的问题

并发引发问题的根源归咎于三个方面:QHW28资讯网——每日最新资讯28at.com

(1)可见性: CPU缓存引起

可见性:一个线程对共享变量的修改,另外一个线程能够立刻看到。QHW28资讯网——每日最新资讯28at.com

举个简单的例子,看下面这段代码:QHW28资讯网——每日最新资讯28at.com

//线程1执行的代码int i = 0;i = 10; //线程2执行的代码j = i;

在多线程环境下,如果线程1对变量i进行了修改,但由于CPU缓存的存在,这个修改可能并不会立即被其他线程(比如线程2)所看到。这样,在线程2执行j = i;时,它可能读取到的是旧的i的值,而不是线程1修改后的新值。QHW28资讯网——每日最新资讯28at.com

(2)原子性: 分时复用引起

原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。 经典的转账问题:比如从账户A向账户B转1000元,那么必然包括2个操作:从账户A减去1000元,往账户B加上1000元。 试想一下,如果这2个操作不具备原子性,会造成什么样的后果。假如从账户A减去1000元之后,操作突然中止。然后又从B取出了500元,取出500元之后,再执行 往账户B加上1000元 的操作。这样就会导致账户A虽然减去了1000元,但是账户B没有收到这个转过来的1000元。 所以这2个操作必须要具备原子性才能保证不出现一些意外的问题。QHW28资讯网——每日最新资讯28at.com

(3)有序性: 重排序引起

QHW28资讯网——每日最新资讯28at.com

有序性:即程序执行的顺序按照代码的先后顺序执行。举个简单的例子,看下面这段代码:QHW28资讯网——每日最新资讯28at.com

int i = 0;              boolean flag = false;i = 1;                //语句1  flag = true;          //语句2

上面代码定义了一个int型变量,定义了一个boolean类型变量,然后分别对两个变量进行赋值操作。从代码顺序上看,语句1是在语句2前面的,那么JVM在真正执行这段代码的时候会保证语句1一定会在语句2前面执行吗? 不一定,为什么呢? 这里可能会发生指令重排序。QHW28资讯网——每日最新资讯28at.com

3.CountDownLatch和CyclicBarrier如何让多线程步调一致

在多线程编程中,有时我们需要让多个线程协同工作,以便在某个点上保持步调一致。Java中的CountDownLatch和CyclicBarrier就是用来实现这一目的的两个重要工具。QHW28资讯网——每日最新资讯28at.com

(1)CountDownLatch

实现原理:QHW28资讯网——每日最新资讯28at.com

CountDownLatch是一个计数器,它允许一个或多个线程等待一组操作完成。其基本思想是,一个线程或多个线程在执行任务时,需要等待其他线程都执行完毕后才能继续执行。CountDownLatch通过一个计数器来实现,当计数器为0时,等待的线程可以继续执行。QHW28资讯网——每日最新资讯28at.com

QHW28资讯网——每日最新资讯28at.com

这段代码演示了使用CountDownLatch来实现多个线程之间的协同工作,确保它们按照预期顺序执行。QHW28资讯网——每日最新资讯28at.com

import java.util.concurrent.CountDownLatch;public class Main {    public static void main(String[] args) throws InterruptedException {        CountDownLatch latch = new CountDownLatch(3); // 初始化计数器为3        Runnable task = () -> {            // 执行一些操作            latch.countDown(); // 操作完成后将计数器减1        };        for (int i = 0; i < 3; i++) {            new Thread(task).start(); // 启动3个线程执行任务        }        latch.await(); // 等待计数器变为0        System.out.println("所有操作已完成,多线程步调一致!");    }}

当3个线程都调用了countDown之后,主线程从await返回,并输出"所有操作已完成,多线程步调一致!QHW28资讯网——每日最新资讯28at.com

(2)CyclicBarrier

实现原理:QHW28资讯网——每日最新资讯28at.com

字面意思回环栅栏,通过它可以实现让一组线程等待至某个状态之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。我们暂且把这个状态就叫做barrier,当调用await()方法之后,线程就处于barrier了。QHW28资讯网——每日最新资讯28at.com

QHW28资讯网——每日最新资讯28at.com

这段代码演示了如何使用CyclicBarrier来实现多个线程在一个屏障点进行等待,并在达到该位置后同时继续执行后续操作。CyclicBarrier常用于多个线程协同工作,并且需要在某个点上实现同步,在实际场景中可以用于控制多线程分阶段执行任务的情况。QHW28资讯网——每日最新资讯28at.com

import java.util.concurrent.CyclicBarrier;public class Main {    public static void main(String[] args) {        CyclicBarrier barrier = new CyclicBarrier(3, () -> {            System.out.println("所有线程已到达栅栏位置,开始执行后续操作!");        });        Runnable task = () -> {            try {                // 执行一些操作                barrier.await(); // 等待其他线程到达栅栏位置            } catch (Exception e) {                e.printStackTrace();            }        };        for (int i = 0; i < 3; i++) {            new Thread(task).start(); // 启动3个线程执行任务        }    }}

4.总结

CountDownLatch 和 CyclicBarrier 都是 Java 多线程编程中用于控制多个线程协同工作的工具,但它们之间有一些关键的区别,用法的区别如下:CountDownLatch 主要用来解决一个线程等待多个线程的场景,可以类比旅游团团长要等待所有的游客到齐才能去下一个景点;而CyclicBarrier 是一组线程之间互相等待,更像是几个驴友之间不离不弃。QHW28资讯网——每日最新资讯28at.com

(1)功能不同:

  • CountDownLatch 用于让一个或多个线程等待其他线程完成操作,达到某个条件后再继续执行。
  • CyclicBarrier 则用于让多个线程在指定位置处进行等待,然后同时继续执行。

(2)重用性:

  • CountDownLatch 是一次性的,一旦计数器变为0,就不能再重置使用。
  • CyclicBarrier 可以被重复使用,当所有线程都到达屏障点后,可以选择重置栅栏来进行下一轮等待。

(3)回调操作:

  • CountDownLatch 没有提供回调操作的机制。
  • CyclicBarrier 可以在所有线程到达屏障点后执行指定的合并操作。

(4)适用场景:

  • CountDownLatch 适用于一组线程需要等待另一组线程执行完毕后再执行的情况,或者等待某些条件满足后再继续执行。
  • CyclicBarrier 适用于多个线程需要在特定点同步,并且在这一点上需要同时继续执行后续操作的情况。

总的来说,CountDownLatch的适用场景更倾向于等待其他线程的任务完成,而CyclicBarrier更适用于多个线程在特定位置同步后继续执行。两者都是非常有用的并发控制工具,能够帮助程序员更加灵活地管理多线程任务的执行顺序。QHW28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-80833-0.html并发协调神器CountDownLatch和CyclicBarrier

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: JSDoc:一个可选的 TypeScript 替代品

下一篇: 一文理解Python的全局解释器锁(GIL)

标签:
  • 热门焦点
  • 小米官宣:2023年上半年出货量中国第一!

    今日早间,小米电视官方微博带来消息,称2023年小米电视上半年出货量达到了中国第一,同时还表示小米电视的巨屏风暴即将开始。“公布一个好消息2023年#小米电视上半年出货量中国
  • 0糖0卡0脂 旭日森林仙草乌龙茶优惠:15瓶到手29元

    旭日森林无糖仙草乌龙茶510ml*15瓶平时要卖为79.9元,今日下单领取50元优惠券,到手价为29.9元。产品规格:0糖0卡0脂,添加草本仙草汁,清凉爽口,富含茶多酚,保留
  • JavaScript 混淆及反混淆代码工具

    介绍在我们开始学习反混淆之前,我们首先要了解一下代码混淆。如果不了解代码是如何混淆的,我们可能无法成功对代码进行反混淆,尤其是使用自定义混淆器对其进行混淆时。什么是混
  • 虚拟键盘 API 的妙用

    你是否在遇到过这样的问题:移动设备上有一个固定元素,当激活虚拟键盘时,该元素被隐藏在了键盘下方?多年来,这一直是 Web 上的默认行为,在本文中,我们将探讨这个问题、为什么会发生
  • 重估百度丨“晚熟”的百度云,能等到春天吗?

    &copy;自象限原创作者|程心排版|王喻可2016年7月13日,百度云计算战略发布会在北京举行,宣告着百度智能云的正式启程。彼时的会场座无虚席,甚至排队排到了门外,在场的所有人几乎都
  • 猿辅导与新东方的两种“归途”

    作者|卓心月 出品|零态LT(ID:LingTai_LT)如何成为一家伟大企业?答案一定是对&ldquo;势&rdquo;的把握,这其中最关键的当属对企业战略的制定,且能够站在未来看现在,即使这其中的
  • ESG的面子与里子

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之三伏大幕拉起,各地高温预警不绝,但处于厄尔尼诺大&ldquo;烤&rdquo;之下的除了众生,还有各大企业发布的ESG报告。ESG是&ldquo;环境保
  • 超级标准版旗舰!iQOO 11S全球首发iQOO超算独显芯片

    上半年已接近尾声,截至目前各大品牌旗下的顶级旗舰都已悉数亮相,而下半年即将推出的顶级旗舰已经成为了数码圈爆料的主流,其中就包括全新的iQOO 11S系
  • AI艺术欣赏体验会在上海梅赛德斯奔驰中心音乐俱乐部上演

    光影交错的镜像世界,虚实幻化的视觉奇观,虚拟偶像与真人共同主持,这些场景都出现在2019世界人工智能大会的舞台上。8月29日至31日,“AI艺术欣赏体验会”在上海
Top