news 2026/6/15 10:28:03

Java 并发编程实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 并发编程实战

开篇词 | 你为什么需要学习并发编程?



文章目录

  • 开篇词 | 你为什么需要学习并发编程?
  • 学习攻略 | 如何才能学好并发编程?
    • 跳出来,看全景
    • 1. 分工
    • 2. 同步
    • 3. 互斥
    • 钻进去,看本质
    • 总结
    • 课后精彩留言

其实并发编程可以总结为三个核心问题:分工、同步和互斥。

分工:指的是如何高效地拆解任务并分配给线程。
同步:指的是线程之间如何协作。
互斥:指的是保证同一时刻只允许一个线程访问共享资源。




学习攻略 | 如何才能学好并发编程?


并发编程并不是一门相对独立的学科,而是一个综合学科。并发编程相关的概念和技术看上非常零散,相关度也很低,总给你一种这样的感觉:我已经学习很多相关技术了,可还是搞不定并发编程。那如何才能学习好并发编程呢?

其实很简单,只要你能从两个方面突破一下就可以了。一个是“跳出来,看全景”,另一个是“钻进去,看本质”。

跳出来,看全景

我们先说“跳出来”。你应该也知道,学习最忌讳的就是“盲人摸象”,只看到局部,而没有看到全局。所以,你需要从一个个单一的知识和技术中“跳出来”,高屋建瓴地看并发编程。当然,这首要之事就是你建立起一张全景图。

1. 分工

所谓分工,类似于现实中一个组织完成一个项目,项目经理要拆分任务,安排合适的成员去完成。

在并发编程领域,你就是项目经理,线程就是项目组成员。任务分解和分工对于项目成败非常关键,不过在并发领域里,分工更重要,它直接决定了并发程序的性能。

Java SDK 并发包里的 Executor、Fork/Join、Future 本质上都是一种分工方法。除此之外,并发编程领域还总结了一些设计模式,基本上都是和分工方法相关的,例如生产者 - 消费者、Thread-Per-Message、Worker Thread 模式等都是用来指导你如何分工的。

2. 同步

在并发编程领域里的同步,主要指的就是线程间的协作,本质上和现实生活中的协作没区别,不过是一个线程执行完了一个任务,如何通知执行后续任务的线程开工而已。

协作一般是和分工相关的。Java SDK 并发包里的 Executor、Fork/Join、Future 本质上都是分工方法,但同时也能解决线程协作的问题。例如,用 Future 可以发起一个异步调用,当主线程通过 get() 方法取结果时,主线程就会等待,当异步执行的结果返回时,get() 方法就自动返回了。主线程和异步线程之间的协作,Future 工具类已经帮我们解决了。除此之外,Java SDK 里提供的 CountDownLatch、CyclicBarrier、Phaser、Exchanger 也都是用来解决线程协作问题的。

不过还有很多场景,是需要你自己来处理线程之间的协作的。

工作中遇到的线程协作问题,基本上都可以描述为这样的一个问题:当某个条件不满足时,线程需要等待,当某个条件满足时,线程需要被唤醒执行。例如,在生产者 - 消费者模型里,也有类似的描述,“当队列满时,生产者线程等待,当队列不满时,生产者线程需要被唤醒执行;当队列空时,消费者线程等待,当队列不空时,消费者线程需要被唤醒执行。”

在 Java 并发编程领域,解决协作问题的核心技术是管程,上面提到的所有线程协作技术底层都是利用管程解决的。管程是一种解决并发问题的通用模型,除了能解决线程协作问题,还能解决下面我们将要介绍的互斥问题。

可以这么说,管程是解决并发问题的万能钥匙。

3. 互斥

分工、同步主要强调的是性能,但并发程序里还有一部分是关于正确性的,用专业术语叫“线程安全”。并发程序里,当多个线程同时访问同一个共享变量的时候,结果是不确定的。

导致不确定的主要源头是缓存导致的可见性问题、线程切换带来的原子性问题、编译优化带来的有序性问题和。为了解决这三个问题,Java 语言引入了内存模型,内存模型提供了一系列的规则,利用这些规则,我们可以避免可见性问题、有序性问题,但是还不足以完全解决线程安全问题。解决线程安全问题的核心方案还是互斥。

所谓互斥,指的是同一时刻,只允许一个线程访问共享变量。

实现互斥的核心技术就是锁,Java 语言里 synchronized、SDK 里的各种 Lock 都能解决互斥问题。虽说锁解决了安全性问题,但同时也带来了性能问题,那如何保证安全性的同时又尽量提高性能呢?

  • 可以分场景优化,Java SDK 里提供的 ReadWriteLock、StampedLock 就可以优化读多写少场景下锁的性能。
  • 还可以使用无锁的数据结构,例如 Java SDK 里提供的原子类都是基于无锁技术实现的。
  • 除此之外,还有一些其他的方案,原理是不共享变量或者变量只允许读。这方面,Java 提供了 Thread Local 和 final 关键字,还有一种 Copy-on-write 的模式。

使用锁除了要注意性能问题外,还需要注意死锁问题。

跳出来,看全景,可以让你的知识成体系,所学知识也融汇贯通起来,由点成线,由线及面,画出自己的知识全景图。

并发编程全景图之思维导图

钻进去,看本质

但是光跳出来还不够,还需要下一步,就是在某个问题上钻进去,深入理解,找到本质。

我属于理论派,我认为工程上的解决方案,一定要有理论做基础。所以在学习并发编程的过程中,我都会探索它背后的理论是什么。比如,当看到 Java SDK 里面的条件变量 Condition 的时候,我会下意识地问,“它是从哪儿来的?是 Java 的特有概念,还是一个通用的编程概念?”当我知道它来自管程的时候,我又会问,“管程被提出的背景和解决的问题是什么?”这样一路探索下来,我发现 Java 语言里的并发技术基本都是有理论基础的,并且这些理论在其他编程语言里也有类似的实现。所以我认为,技术的本质是背后的理论模型。

总结

当初我学习 Java 并发编程的时候,试图上来就看 Java SDK 的并发包,但是很快就放弃了。原因是我觉得东西太多,眼花缭乱的,虽然借助网络上的技术文章,感觉都看懂了,但是很快就又忘了。实际应用的时候大脑也一片空白,根本不知道从哪里下手,有时候好不容易解决了个问题,也不知道这个方案是不是合适的。

我知道根本原因是,我的并发知识还没有成体系。

我想,要让自己的知识成体系,一定要挖掘 Java SDK 并发包背后的设计理念。Java SDK 并发包是并发大师 Doug Lea 设计的,他一定不是随意设计的,一定是深思熟虑的,其背后是 Doug Lea 对并发问题的深刻认识。可惜这个设计的思想目前并没有相关的论文,所以只能自己琢磨了。

分工、同步和互斥的全景图,是我对并发问题的个人总结,不一定正确,但是可以帮助我快速建立解决并发问题的思路,梳理并发编程的知识,加深认识。我将其分享给你,希望对你也有用。

课后精彩留言


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/15 10:27:39

避坑指南:GD32F30x独立看门狗与窗口看门狗配置的5个常见误区与解决方案

GD32F30x看门狗实战避坑:从异常复位到精准配置的深度解析在嵌入式系统开发中,看门狗定时器是保障系统可靠性的最后一道防线。GD32F30x系列提供的独立看门狗(IWDG)和窗口看门狗(WWDG)看似配置简单,却暗藏诸多技术细节。许多开发者在初次接触时…

作者头像 李华
网站建设 2026/6/15 10:27:31

AI对话设计:重构人机交互的节奏、信任与上下文管理

1. 项目概述:这不是调教AI,而是重建人机对话的底层逻辑“当AI开口说话”——这句标题乍看像科技媒体的软文口号,但在我过去三年深度参与17个企业级对话系统落地项目后,它直指一个被严重低估的现实:90%的AI对话失败&…

作者头像 李华
网站建设 2026/6/15 10:25:58

Proteus仿真STM32温度报警器,这三个调试‘坑’我帮你踩过了

Proteus仿真STM32温度报警器的三大调试陷阱与实战解决方案在嵌入式系统开发中,Proteus与STM32的组合为工程师提供了高效便捷的仿真环境。然而,当涉及到温度报警器这类综合项目时,即便是经验丰富的开发者也会在仿真过程中遭遇意料之外的"…

作者头像 李华
网站建设 2026/6/15 10:25:58

数字电路信号传输与逻辑门设计核心技术解析

1. 信号传输基础与逻辑门设计概述 在数字电路设计中,信号传输是实现逻辑运算的基础。信号通过特定路径(如半导线)在电路中传递,其本质是离散状态的空间转移。这种传输过程遵循严格的数学规律,需要精确控制信号的时间延…

作者头像 李华