并发编程
文章平均质量分 93
本专栏将系统性地为您介绍并发编程中各种核心概念和底层实现逻辑。整合了本人多年编程经验的总结。
YahirQ
你好,我是YahirQ,一个写了十年代码的“老”程序员。
我的技术地图有点广:以 .NET 为根据地,也曾远征 Java、C++、Python 的江湖,并用 Vue、SQL 和 iOS 开发过不少应用。这些经历让我明白,技术之道,万变不离其宗。
而现在,我选择了一条“向下扎根”的道路——嵌入式开发。我着迷于代码如何直接驱动硬件,享受在资源受限的环境下创造价值的乐趣。这对我而言,是一个全新的起点。
在这里,我将以一个“资深新手”的视角,记录并分享从传统软件到嵌入式世界的转型之路。我的文章会力求通俗易懂,既有硬核的代码分析,也有踩坑填坑的实战记录。期待能与志同道合的你一起学习,共同成长!
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
深入浅出 协程(Coroutine):从原理到实践
协程是一种轻量级的并发编程模型,允许在单线程内实现多个可挂起和恢复的执行流。与线程相比,协程采用协作式调度,由用户主动让出CPU,避免了锁的使用,且资源开销极低,单个线程可支持数十万协程。协程分为有栈和无栈两种类型,适用于高并发网络服务、I/O密集型任务等场景。主流语言如Go、Python、JavaScript等均提供协程支持,但协程无法直接利用多核CPU,且需避免阻塞操作。典型应用包括Web服务器、微服务和流式数据处理等,能显著提升系统并发吞吐量。原创 2026-04-11 16:00:29 · 799 阅读 · 0 评论 -
分布式锁(Distributed lock)
分布式锁是用于分布式系统中协调共享资源访问的互斥机制,确保同一时间只有一个客户端能访问资源。主要实现方式包括:基于数据库(简单但性能差)、基于Redis(高性能但不保证强一致性)和基于ZooKeeper/etcd(强一致但性能中等)。分布式锁需满足互斥性、可重入性、锁超时释放等特性,并应对锁超时、死锁、网络分区等挑战。最佳实践包括设置合理超时时间、细粒度锁、唯一标识校验等。选择方案时应根据业务对一致性、性能和可用性的需求权衡。原创 2026-02-27 22:56:28 · 1257 阅读 · 0 评论 -
【多核同步硬件机制】独占监视器(Exclusive Monitor)
独占监视器是多核处理器中支持原子操作的硬件机制,通过LL/SC指令对实现无锁同步。核心执行LL时标记监视的内存地址,SC仅在地址未被修改时成功写入。该机制避免了总线锁,高效支持CAS等原子操作,但需处理缓存行粒度、上下文切换等问题。不同架构(如ARM、MIPS、RISC-V)实现方式各异,x86则通过缓存一致性协议达到类似效果。独占监视器是构建上层同步原语的基础硬件支持。原创 2025-12-09 20:16:51 · 1000 阅读 · 0 评论 -
【多线程】可重入锁 Reentrant Lock
可重入锁是一种允许同一线程多次获取同一把锁的同步机制,避免了自死锁问题。文章通过房间门锁的比喻,解释了可重入锁的核心概念:记录持有线程和重入次数。分析了非可重入锁在递归调用和方法互调时会导致死锁的问题,并展示了Java中两种可重入锁实现方式 - synchronized关键字和ReentrantLock类。可重入锁通过维护持有线程和计数器,使同一线程可以安全地多次获取锁,是面向对象编程中处理复杂调用关系的必备同步工具。原创 2025-10-21 19:06:22 · 937 阅读 · 0 评论 -
【多线程】Future
摘要: Future是多线程编程中处理异步任务结果的核心抽象,代表一个尚未完成的计算结果占位符。它允许主线程提交任务后继续执行其他操作,之后通过Future对象获取计算结果。核心方法包括检查完成状态的isDone()、阻塞获取结果的get()和取消任务的cancel()。Java中通过ExecutorService提交Callable任务获取Future,但基础Future存在回调困难等局限性。Java 8引入的CompletableFuture支持非阻塞回调和任务组合,提供更强大的异步编程能力。其他语言如原创 2025-10-20 22:09:25 · 891 阅读 · 0 评论 -
【多线程】并行编程模型 OpenMP
OpenMP是一种用于共享内存系统的并行编程模型,通过编译指令、库函数和环境变量实现多线程并行。其核心是Fork-Join执行模型:程序从单线程开始,遇到并行指令时分叉出线程团队并行执行,结束后再合并为单线程。主要组件包括#pragma指令(如parallel for)、库函数(如获取线程ID)和环境变量(如设置线程数)。OpenMP的优势在于简单易用、可移植性强,特别适合循环并行化,只需添加少量指令即可显著提升CPU密集型任务的性能。这种模型让开发者能专注于算法而无需直接管理线程细节。原创 2025-10-20 21:55:46 · 1123 阅读 · 0 评论 -
【多线程】门栓/闭锁(Latch/CountDownLatch)
闭锁(CountDownLatch)是一种线程同步工具,通过计数器机制实现线程间协作。核心特点是:初始化时设定计数器值;线程调用countDown()递减计数;调用await()的线程会阻塞直到计数归零。典型应用场景包括服务依赖等待、多线程任务同步等。与CyclicBarrier不同,闭锁是一次性使用的,更强调"事件完成"而非线程相互等待。Java中的CountDownLatch类提供了简洁的实现,适合需要等待多个操作完成的并发控制场景。原创 2025-10-13 22:28:31 · 1242 阅读 · 0 评论 -
【多线程】阻塞等待(Blocking Wait)(以C++为例)
阻塞等待是多线程编程中的核心机制,指线程在条件不满足时暂停执行并释放CPU资源。相比忙等待(自旋锁),它更节约CPU但会增加上下文切换开销。C++中常见的阻塞等待场景包括:互斥锁(std::mutex)获取、条件变量(std::condition_variable)等待、线程join操作、带超时的等待以及future/promise异步操作。合理使用阻塞等待能提高多线程程序效率,避免资源浪费。文章通过多个C++代码示例展示了不同阻塞等待的实现方式及其适用场景。原创 2025-10-12 22:28:02 · 1368 阅读 · 0 评论 -
【多线程】阻塞等待(Blocking Wait)(以Java为例)
多线程编程中的阻塞等待(Blocking Wait)是线程在条件不满足时主动暂停执行的机制。相比忙等待(busy-waiting),阻塞等待能避免CPU资源浪费,但会带来线程切换开销。Java中常见的阻塞场景包括:同步锁竞争(synchronized/Lock)、等待通知机制(wait/notify)、线程合并(join)以及阻塞队列操作。线程在阻塞时会进入BLOCKED(等待锁)或WAITING(主动等待)状态。合理使用阻塞等待能提高多线程程序的效率和资源利用率。原创 2025-10-12 22:15:53 · 1086 阅读 · 0 评论 -
【多线程】忙等待/自旋(Busy Waiting/Spinning)
文章摘要 忙等待(自旋)是一种线程等待策略,线程通过循环检查条件是否满足而不释放CPU资源。优点是响应快、无上下文切换,但会浪费大量CPU资源。适用于等待时间极短的场景(如自旋锁)。大多数情况下应使用阻塞等待(如条件变量、信号量),让线程在等待时进入睡眠状态。现代系统常采用自适应策略,先自旋后阻塞以平衡性能与资源消耗。原创 2025-10-10 22:07:39 · 1360 阅读 · 0 评论 -
【多线程】屏障/栅栏(Barrier)
屏障(Barrier)是一种多线程同步机制,允许多个线程在共同执行点相互等待。其核心思想是"同进同退"——所有线程必须到达屏障点才能继续执行,否则先到的线程会阻塞等待。屏障主要用于分阶段任务的同步,如并行计算、系统模拟等场景。Java中的CyclicBarrier是典型实现,可循环使用,当所有线程调用await()后,屏障会重置并唤醒所有线程继续执行。与一次性使用的闭锁不同,屏障支持多阶段同步,适用于需要重复协作的并行任务。合理使用屏障能有效管理复杂多线程程序的执行流程。原创 2025-10-10 21:07:23 · 1099 阅读 · 0 评论 -
【多线程】线程池(Thread Pool)
摘要: 线程池通过池化技术预先创建并管理线程,避免频繁创建/销毁线程的开销。其核心优势包括降低资源消耗、提高响应速度、增强线程可控性。线程池由任务队列、工作线程和线程池管理器组成,通过核心参数(核心线程数、最大线程数、任务队列等)实现任务调度。Java中的ThreadPoolExecutor提供灵活配置,而Executors工具类可快速创建常用线程池(如固定大小、缓存型等)。正确使用线程池能显著提升多线程应用的性能和稳定性,是高并发开发的必备技术。原创 2025-10-08 21:31:47 · 1465 阅读 · 0 评论 -
【多线程】死锁(deadlock)
在计算机科学中,死锁是指两个或两个以上的并发进程(或线程),在彼此等待对方释放所占有的资源,但在没有外部干预的情况下,所有进程都无法继续推进的一种状态。死锁是多线程编程中一个必须警惕的“陷阱”。它源于多个执行流对有限资源的竞争和不当的获取顺序。理解其产生的四个必要条件,并采取相应的预防策略(尤其是按顺序获取锁),是编写健壮、可靠的多线程程序的关键。在复杂系统中,还需要借助工具来检测和分析潜在的死锁。原创 2025-10-08 21:27:19 · 809 阅读 · 0 评论 -
【多线程】读写锁(Read-Write Lock)是什么?
读写锁是一种同步机制,用于优化读多写少场景下的并发性能。它区分读操作(可共享)和写操作(需独占),允许多个读线程同时访问数据,而写操作则需互斥执行。相比互斥锁,读写锁提高了读操作的并发度,但需注意潜在的写线程饥饿问题。Java中的ReentrantReadWriteLock是其典型实现,适用于高并发读取、低频修改的场景,在保证数据一致性的同时显著提升系统吞吐量。原创 2025-10-05 20:19:18 · 631 阅读 · 0 评论 -
【多线程】多线程的底层实现
多线程的底层实现涉及软硬件协同工作。操作系统层面通过用户级线程、内核级线程或混合模型管理线程,其中混合模型结合了两者优势。硬件层面依靠多核处理器实现真正并行,超线程技术则提升单核利用率。核心机制是线程上下文切换,包括保存/恢复线程状态和调度过程。整个过程由编程语言线程库、操作系统内核和CPU硬件分层协作完成,实现并发执行效果。原创 2025-10-05 19:36:23 · 961 阅读 · 0 评论 -
【多线程】线程休眠(Thread Sleep)的底层实现
线程休眠的底层实现涉及从用户态到内核态的复杂交互。其核心是将线程从就绪队列移入等待队列,主动让出CPU。当休眠条件满足时,线程被重新放回就绪队列。具体实现包括:编程语言层调用本地方法,操作系统层通过系统调用(如nanosleep)设置线程状态、启动定时器并加入等待队列,硬件层依赖高精度时钟源和中断机制实现精确唤醒。整个过程涉及线程状态切换(RUNNING→SLEEPING→RUNNING)和内核调度机制,确保休眠期间不消耗CPU资源。原创 2025-10-04 20:48:46 · 974 阅读 · 0 评论 -
【多线程】条件变量(Condition Variable)是什么?
条件变量是解决线程同步中"忙等待"问题的核心工具,通过与互斥锁配合使用,允许线程在条件不满足时主动阻塞并释放锁,待条件满足时被其他线程唤醒。文章通过外卖等待的生动比喻解释了其工作原理,并详细介绍了等待(wait)、通知(signal)和广播(broadcast)三个核心操作。重点强调了必须使用while循环检查条件以防止虚假唤醒,并提供了生产者-消费者模型的代码示例。条件变量能有效消除忙等待,实现线程间高效协作,是解决生产者-消费者等经典同步问题的基础。原创 2025-09-26 09:00:00 · 930 阅读 · 0 评论 -
【多线程】无锁数据结构(Lock-Free Data Structures)是什么?
无锁数据结构是一种通过原子操作(如CAS)实现线程安全访问的并发编程技术,避免了传统锁机制带来的阻塞、死锁和性能瓶颈问题。其核心思想是让线程通过重试机制而非互斥锁来协调共享数据的访问。虽然无锁结构能提供更高的并发性和可扩展性,但也面临实现复杂、可能出现ABA问题等挑战。这种技术适用于对性能要求极高的场景,如操作系统内核和高并发系统,但需要谨慎使用。原创 2025-10-04 16:01:18 · 1210 阅读 · 0 评论 -
【多线程】计算机领域中的各种锁
本文系统梳理了计算机领域常见的锁类型,从实现层面、设计思想、状态策略等维度进行分类比较。表格详细列举了互斥锁、读写锁、自旋锁等12种锁的核心特征和典型应用,特别分析了Java中synchronized的锁升级优化机制。文章建议根据具体场景选择锁类型:高并发读场景适合读写锁,短临界区可用自旋锁,线程协作推荐条件变量,并指出JVM会智能进行锁升级和锁粗化来优化性能。原创 2025-09-25 21:20:53 · 756 阅读 · 0 评论 -
【多线程】信号量(Semaphore)常见的应用场景
信号量是一种重要的同步机制,主要用于多线程环境下的资源访问控制。其核心应用场景包括:1)互斥访问,通过二进制信号量保护临界区;2)线程同步,协调执行顺序,如生产者-消费者模型;3)资源池管理,控制有限资源的分配;4)并发限制,防止系统过载。信号量分为二进制和计数两种类型,初始值根据场景设置。现代编程中互斥锁更适合简单互斥场景,而信号量在复杂同步和并发控制方面具有独特优势。原创 2025-09-23 20:18:22 · 889 阅读 · 0 评论 -
【多线程】什么是原子操作(Atomic Operation)?
原子操作是不可分割的操作,要么完全执行,要么完全不执行,确保多线程环境下的数据安全。非原子操作(如i++)可能因线程切换导致数据竞争。原子操作通过硬件实现,单核CPU通过关闭中断保证原子性,多核CPU利用总线锁或缓存一致性协议(如MESI)实现细粒度同步,避免使用高开销的软件锁。常见原子指令包括CAS和LL/SC,其低开销特性使其适用于计数器等简单场景,而互斥锁更适合复杂逻辑。原子操作是构建并发控制的基础。原创 2025-09-28 22:17:45 · 1035 阅读 · 0 评论 -
【多线程】信号量(Semaphore)是什么?
信号量是一种用于控制多线程/多进程访问共享资源的同步机制,通过计数器协调资源访问。核心包括P操作(申请资源时计数器减1,若为0则阻塞)和V操作(释放资源时计数器加1并唤醒等待线程)。分为二进制信号量(类似互斥锁,值0或1)和计数信号量(管理多个资源)。与互斥锁不同,信号量无所有者概念,任何线程都可释放资源。它既能实现互斥访问,也能用于资源计数和线程同步,是解决生产者-消费者等并发问题的有效工具。原创 2025-09-23 10:52:45 · 994 阅读 · 0 评论 -
【多线程】临界区(Critical Section)是什么?
临界区(Critical Section)是多线程编程中访问共享资源的代码段,必须确保同一时间仅有一个线程执行,以防止数据竞争和错误。通过互斥锁等同步机制保护临界区,可避免多个线程同时操作共享资源导致的不一致问题。临界区应尽可能短小,并使用RAII技术自动管理锁,以提高程序安全性和性能。理解临界区是多线程编程确保数据一致性的关键。原创 2025-09-26 09:30:00 · 1577 阅读 · 0 评论 -
【多线程】竞态条件(race condition)是什么?
竞态条件 是指一个系统或进程的输出,依赖于不受控制的事件发生的顺序或时机。当多个线程/进程同时访问和操作共享数据时,最终的执行结果取决于它们执行的精确顺序,而这个顺序是无法预测的,从而导致不可预知的行为。两个线程的执行顺序交织在了一起,导致了错误的结果。解决竞态条件的核心思想是:将“读写共享资源”的关键代码段变成一个原子操作,即在同一时刻,只有一个线程可以执行这段代码。简单来说,竞态条件就是一个因为“抢”资源而引发的混乱状态,而解决之道就是建立“排队”或“独占”的规则(锁)。竞态条件产生的必要条件。原创 2025-09-30 23:21:14 · 1069 阅读 · 0 评论 -
【多线程】互斥锁(Mutex)是什么?
互斥锁(Mutex)是多线程编程中的关键同步工具,用于实现线程间的互斥访问。它通过加锁(Lock)和解锁(Unlock)操作保护临界区,确保同一时间只有一个线程能访问共享资源,防止数据竞争。互斥锁具有所有权特性,必须由加锁线程解锁,与信号量不同。典型应用场景如银行账户操作,多个线程同时取款时,互斥锁能保证余额计算的正确性。互斥锁简单直观,是构建线程安全程序的基础机制。原创 2025-09-24 22:38:55 · 1181 阅读 · 0 评论 -
【多线程】监视器(Monitor)是什么?
监视器(Monitor)是一种高级同步机制,将共享数据及操作方法封装为独立模块,通过内置互斥锁确保单线程访问,并利用条件变量实现线程间协作。其核心特性包括:1)自动互斥,任一时刻仅允许一个线程执行监视器内方法;2)提供wait()/notify()机制管理线程等待与唤醒。典型实现如Java的synchronized块,通过隐式锁管理简化并发编程,避免显式锁操作的复杂性。相比底层互斥锁+条件变量的组合,监视器通过语言级封装显著提升开发安全性与易用性,适用于生产者-消费者等经典同步问题。本质上是互斥与原创 2025-09-27 16:56:47 · 1076 阅读 · 0 评论
分享