仓颉 std.sync 多条件变量互斥锁:MultiConditionMonitor 单互斥体多等待队列并发原语详解

发布时间:2026/10/15 6:03:14

仓颉 std.sync 多条件变量互斥锁:MultiConditionMonitor 单互斥体多等待队列并发原语详解 人工智能AI 技能文档开发工具【免费下载链接】DocAgent项目地址https://gitcode.com/Cangjie-SIG/DocAgent点击查看免费下载MultiConditionMonitor是仓颉标准库std.sync中用于实现单互斥体、多等待队列线程同步机制的类它允许在同一把互斥锁上绑定多个条件变量每个条件变量各自维护独立的等待队列从而支持比单一Monitor更精细的线程挂起与唤醒控制。本文以该类在仓库中的 API 文档std/sync/sync_package_index/MultiConditionMonitor_class.md为主体结合 std/sync 包 API 文档 中的完整声明与异常定义、sync 包使用示例 及 std.sync 包总览系统讲解其构造方式、四个核心成员函数newCondition/notify/notifyAll/wait的语义与异常边界、典型编码范式并给出向MutexCondition迁移的对照方案。一、MultiConditionMonitor 在 std.sync 中的定位std.sync包为仓颉语言提供并发编程能力包括原子操作、可重入互斥锁、基于共享变量的线程同步机制以及定时器等功能见 std.sync 包总览。仓颉线程采用 M:N 线程模型本质上是一种用户态轻量级线程支持抢占可通过spawn关键字创建。在线程同步机制中仓库文档明确给出了三类演进关系Monitor已标注 deprecated提供单条件变量的挂起/唤醒能力文档建议未来版本使用Condition接口替代MultiConditionMonitor已标注 deprecated在同一个互斥锁上绑定多个条件变量解决Monitor单条件队列不足以表达同一种共享状态需要按不同条件分别等待/唤醒这类高级并发算法的场景MutexCondition当前推荐方案Mutex.condition()可创建与该锁关联的Condition实现单 Lock 多等待队列的并发原语。MultiConditionMonitor的官方定位是提供对同一个互斥锁绑定多个条件变量的功能并且该类应仅当在Monitor类不足以实现高级并发算法时被使用见 sync_package_classes.md 中MultiConditionMonitor一节的注意说明。也就是说绝大多数场景应优先使用Monitor或其替代Condition只有当需要同一把锁上划分多个独立的等待队列时才考虑该类同时它已被标记为未来版本即将废弃使用Mutex替代。二、类声明与继承关系根据仓库 API 文档MultiConditionMonitor的完整类声明为public class MultiConditionMonitor : ReentrantMutex { public init() }声明位于 sync_package_classes.md 中MultiConditionMonitor一节。它继承自ReentrantMutex同为 deprecated建议用Mutex替代。这意味着MultiConditionMonitor实例天然具备可重入互斥锁的全部能力继承方法原型语义lockpublic open func lock(): Unit锁定互斥体若已被其他线程持有则阻塞当前线程tryLockpublic open func tryLock(): Bool尝试锁定成功返回true已被锁定返回falseunlockpublic open func unlock(): Unit解锁若被重复加锁 N 次需调用 N 次才完全解锁可重入互斥锁的作用是对临界区加以保护使得任意时刻最多只有一个线程能够执行临界区代码可重入是指线程获取该锁后可以再次获得该锁。这些方法的定义可在ReentrantMutex一节sync_package_classes.md中查阅。因此在使用MultiConditionMonitor时锁的获取与释放lock/unlock是后续所有条件变量操作的前置条件——这一点与后文成员函数的异常定义密切相关。三、构造函数init()MultiConditionMonitor只提供默认构造函数名称原型说明init()通过默认构造函数创建 MultiConditionMonitor创建实例时需要注意文档中的关键语义初始化时MultiConditionMonitor没有与之相关的条件变量。所有条件变量都必须通过后续的newCondition调用动态创建每次调用都会产生一个新的等待队列并返回一个唯一标识符。四、成员函数详解MultiConditionMonitor的四个核心成员函数构成了完整的创建条件 → 挂起等待 → 定向唤醒闭环。以下逐一说明其原型、语义、返回值与异常边界。4.1 newCondition()创建条件变量public func newCondition(): ConditionID功能创建一个与该 Monitor 相关的ConditionID可能被用来实现单互斥体多等待队列的并发原语。返回值新的ConditionID类型实例作为该条件变量的唯一标识符。异常IllegalSynchronizationStateException——如果当前线程没有持有该互斥体抛出异常。也就是说newCondition必须在持有锁的状态下调用与Mutex.condition()的约束一致见下文迁移章节且每次调用都会向当前对象登记一个新的等待队列。4.2 notify(ConditionID)唤醒单个等待线程public func notify(condID: ConditionID): Unit功能唤醒等待在所指定条件变量上的线程如果有。参数condID: ConditionID——目标条件变量。异常IllegalSynchronizationStateException——如果当前线程没有持有该互斥体或condID不是由该MultiConditionMonitor实例通过newCondition函数创建时抛出异常。notify是定向唤醒即使同一把锁上存在多个等待队列它也只会影响condID对应的那一个队列中的一个线程。4.3 notifyAll(ConditionID)唤醒指定队列的全部线程public func notifyAll(condID: ConditionID): Unit功能唤醒所有等待在所指定条件变量上的线程如果有。参数condID: ConditionID——目标条件变量。异常与notify相同——当前线程未持有互斥体或condID并非由本实例的newCondition创建时抛出IllegalSynchronizationStateException。与notify的差异在于作用范围notifyAll会把condID对应等待队列中的所有线程全部唤醒而不是只唤醒一个。4.4 wait(ConditionID, Duration)挂起等待public func wait(condID: ConditionID, timeout!: Duration Duration.Max): Bool功能当前线程挂起直到对应的notify/notifyAll函数被调用。参数condID: ConditionID——条件变量timeout!: Duration Duration.Max——挂起时间具名参数默认值为Duration.Max表示不设超时上限一直等到被唤醒。返回值Bool——如果该 Monitor 指定的条件变量被其他线程唤醒返回true如果超时则返回false。异常IllegalSynchronizationStateException——如果当前线程没有持有该互斥体或者挂起时间超过timeout或condID不是由该MultiConditionMonitor实例通过newCondition函数创建时抛出异常IllegalArgumentException——如果timeout小于等于Duration.Zero抛出异常。wait的互斥语义十分关键文档中特别说明线程在进入等待时会释放对应的互斥锁被唤醒后再次持有互斥锁。这保证了等待期间其他线程可以进入临界区修改共享变量并执行唤醒操作从而避免死锁。这一行为与Monitor.wait()、Condition.wait()完全一致。五、ConditionID条件变量的唯一标识newCondition返回的ConditionID在仓库中定义为结构体public struct ConditionID见 std/sync/sync_package_index/ConditionID_struct.md 与 sync_package_structs.md。其官方功能说明为用于表示互斥锁的条件变量且同样标注 deprecated建议使用Condition接口替代。作为值类型的标识符ConditionID需要在notify/notifyAll/wait中作为参数传入以指明操作作用于哪一条等待队列。文档同时强调了它的归属约束只有由同一个MultiConditionMonitor实例通过newCondition创建出来的ConditionID才是合法的混用其他实例产生的标识符会触发IllegalSynchronizationStateException。六、异常处理要点MultiConditionMonitor的操作会涉及两类异常均可在 std/sync 异常文档 与 core 异常文档 中查证异常抛出场景IllegalSynchronizationStateException非法同步状态异常当前线程未持有互斥体就调用newCondition/notify/notifyAll/wait或传入的condID并非本实例newCondition创建或按文档描述挂起时间超过timeout的情形IllegalArgumentException参数非法wait的timeout小于等于Duration.Zero其中IllegalSynchronizationStateException继承自Exception支持init()与init(message: String)两种构造方式可用于携带预定义消息。这一异常设计也从侧面印证了使用规范所有条件变量操作都必须在持有该互斥体的前提下进行这正是单互斥体模型的必然要求。七、典型使用范式同一把锁上的多个独立等待队列MultiConditionMonitor的核心价值在于一个互斥体、多个等待队列。以下示例演示在同一个MultiConditionMonitor上创建两个条件变量两个子线程分别挂起在各自的条件变量上主线程按需定向唤醒代码逻辑参照 sync 包示例 中Monitor的使用范式编写语义严格遵循文档定义import std.sync.* import std.time.* var mcm MultiConditionMonitor() var condA: ConditionID var condB: ConditionID var flagA: Bool true var flagB: Bool true main(): Int64 { // 必须在持有互斥体时创建条件变量 mcm.lock() condA mcm.newCondition() condB mcm.newCondition() mcm.unlock() // 线程 A挂起在 condA 对应的等待队列上 let futA spawn { mcm.lock() while (flagA) { println(Thread A: before wait) mcm.wait(condA) println(Thread A: after wait) } mcm.unlock() } // 线程 B挂起在 condB 对应的等待队列上 let futB spawn { mcm.lock() while (flagB) { println(Thread B: before wait) mcm.wait(condB) println(Thread B: after wait) } mcm.unlock() } // 睡眠一小段时间确保两个子线程都已进入等待 sleep(10 * Duration.millisecond) // 主线程修改共享变量 mcm.lock() flagA false flagB false mcm.unlock() // 定向唤醒只影响 condA 队列 println(Main thread: notify condA) mcm.lock() mcm.notify(condA) mcm.unlock() // 定向唤醒唤醒 condB 队列的全部线程 println(Main thread: notifyAll condB) mcm.lock() mcm.notifyAll(condB) mcm.unlock() // 等待两个子线程完成 futA.get() futB.get() return 0 }典型输出示意实际调度顺序可能因线程时序而不同Thread A: before wait Thread B: before wait Main thread: notify condA Main thread: notifyAll condB Thread A: after wait Thread B: after wait从中可以看到关键点notify(condA)只唤醒队列 A 中的线程notifyAll(condB)只唤醒队列 B 中的线程——两条等待队列在逻辑上完全隔离而临界区共享变量flagA/flagB的修改仍由同一把互斥锁保护。带超时的等待如果希望在限定时长内等待唤醒可使用具名参数timeoutmcm.lock() let woken mcm.wait(condA, timeout: 500 * Duration.millisecond) mcm.unlock() if (woken) { println(condA 被唤醒) } else { println(condA 等待超时) }当超时未获唤醒时wait返回false被其他线程唤醒时返回true。若不传timeout默认Duration.Max则线程将一直挂起直到被唤醒。八、演进与迁移从 MultiConditionMonitor 到 Mutex Condition由于MultiConditionMonitor连同ConditionID、ReentrantMutex、Monitor均已在文档中标注未来版本即将废弃新代码应优先采用MutexCondition组合。仓库中Mutex的完整定义见 sync_package_classes.mdMutex一节与Condition接口见 sync_package_interfaces.md提供了完整的对照关系能力MultiConditionMonitordeprecatedMutex Condition推荐创建条件变量newCondition(): ConditionID需持有锁mutex.condition(): Condition需持有锁唤醒单个线程notify(condID)condition.notify()唤醒全部线程notifyAll(condID)condition.notifyAll()挂起等待wait(condID, timeout! Duration.Max): Boolcondition.wait()/condition.wait(timeout!): Bool条件谓词等待无waitUntil(predicate: ()-Bool)/waitUntil(predicate, timeout!): BoolCondition接口的完整声明为public interface Condition { func notify(): Unit func notifyAll(): Unit func wait(): Unit func wait(timeout!: Duration): Bool func waitUntil(predicate: ()-Bool): Unit func waitUntil(predicate: ()-Bool, timeout!: Duration): Bool }对比可见Condition不仅覆盖了MultiConditionMonitor的全部能力notify/notifyAll/wait还额外提供了waitUntil(predicate)形式的条件谓词等待它会先判断谓词结果若为true则直接返回否则挂起当前线程直到被唤醒且谓词为真这可以有效规避经典的虚假唤醒/信号丢失问题是更高级、更安全的等待范式。仓库中已验证的MutexCondition使用方式见 sync_samples.md 的Mutex与Condition示例展示了标准写法import std.sync.{Mutex, Condition, AtomicBool} var mutex Mutex() var flag AtomicBool(true) main(): Int64 { let condition: Condition synchronized(mutex) { condition mutex.condition() // 在持有锁的情况下生成 Condition 实例 } // ... 子线程通过 condition.waitUntil / condition.notifyAll 完成同步 }需要注意的是无论是MultiConditionMonitor.newCondition()还是Mutex.condition()文档都要求在持有互斥体时调用否则抛出IllegalSynchronizationStateException。同时synchronized关键字配合Lock接口实现如Mutex可以在进入/退出代码块时自动加锁/解锁包括异常与控制转移路径是比手动lock()/unlock()更不易出错的选择。九、小结MultiConditionMonitor是std.sync中面向单互斥体多等待队列场景的线程同步类继承ReentrantMutex同一把锁可绑定多个条件变量每个条件变量对应独立的等待队列完整使用闭环为init()创建实例 → 持有锁时newCondition()创建条件变量并获取ConditionID→ 持有锁时wait(condID[, timeout])挂起 → 持有锁时notify(condID)/notifyAll(condID)定向唤醒所有条件变量操作都要求当前线程持有互斥体且condID必须由本实例的newCondition创建否则抛出IllegalSynchronizationStateException该类以及ConditionID、Monitor、ReentrantMutex均已标注未来版本即将废弃新代码应迁移至MutexCondition后者在同等能力基础上额外提供waitUntil(predicate)条件谓词等待语义更安全、表达能力更强。如需进一步查阅可深入以下仓库文件MultiConditionMonitor 类索引文档、ConditionID 结构体文档、sync 包类 API 文档、sync 包接口文档、sync 包异常文档以及已验证的 sync 包示例。赞分享人工智能AI 技能文档开发工具【免费下载链接】DocAgent项目地址https://gitcode.com/Cangjie-SIG/DocAgent点击查看免费下载相关推荐仓颉 std.sync 并发类详解原子操作、互斥锁、条件变量与定时器的实战指南仓颉 std.sync 并发类详解原子操作、互斥锁、条件变量与定时器的实战指南 本文以仓颉Cangjie标准库 std.sync 包的类 API 文档为主编程语言语言运行时标准库垃圾回收并发编程仓颉标准库 std.sync 并发同步机制全解原子操作、互斥锁、条件变量与定时器仓颉标准库 std.sync 并发同步机制全解原子操作、互斥锁、条件变量与定时器 std.sync 是仓颉编程语言标准库中面向并发编程的核心包为多线程程序提文档知识库教程OpenHarmony仓颉 std.sync 接口体系详解Condition、Lock、UniqueLock 与可重入互斥锁仓颉 std.sync 接口体系详解Condition、Lock、UniqueLock 与可重入互斥锁 本文基于仓颉运行时仓库中 stdlib.sync 包的编程语言语言运行时标准库垃圾回收并发编程上一篇Switch-lan-play 多平台编译实战指南构建你的虚拟局域网联机工具下一篇终极指南SeaTunnel中的JsonPath数据转换插件详解创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/10/15 6:03:14

PPA第六版与AIAG QMC映射落地:控制计划审核避坑指南

简介:VDA 2 EN 6th 2020 PPA AIAG QMC 最新版是德国汽车工业协会(VDA)质量管理中心发布的供应链质量保障指南,聚焦生产过程和产品批准(PPA)环节,面向汽车行业质量工程师、供应商管理人员及供应链…

2026/10/15 5:58:13

AI虚假信息识别与内容安全合规实践

我无法根据该标题生成符合要求的博文内容。原因如下:标题中提及的“Claude Haiku 5.5”“GPT-6”“Manus重返北京”等均为当前(2024年)并不存在的虚构信息。截至2024年,Anthropic尚未发布任何命名为“Claude Haiku 5.5”的模型&am…

2026/10/15 5:58:13

PXE+Kickstart无人值守装机实战:CentOS 7批量部署全链路解析

1. 这不是“装系统”,而是一套可复用的标准化交付流水线你有没有遇到过这样的场景:新采购了20台服务器,需要统一安装CentOS 7并配置基础环境——每台手动操作至少40分钟,光是选择语言、时区、磁盘分区、网络设置、软件包就足够让人…

2026/10/15 7:08:16

YOLOv8路面裂缝检测系统开发实践:从数据到部署全流程

我已经在多个项目里用过YOLO系列做视觉检测,但真正让我觉得“这套流程可以沉淀下来复用”的,还是最近完成的这个路面裂缝检测系统。起因是某交通巡检项目需要把道路裂缝从现场照片里自动识别出来,效率要求接近实时,同时还得应付不…

2026/10/15 7:08:16

审计报告出具与底稿归档:项目收尾阶段的关键控制点与实操指南

1. 审计报告出具前的关键控制点每年到了报告集中出具的那几周,办公室里基本就是两种状态:一种是项目组还没收完数、报告模板改到第八版、合伙人办公室门口排着队等签字;另一种是已经出完报告的人表面上很轻松,但心里还有一个事没落…

2026/10/15 7:08:16

IT资产管理全生命周期解决方案与关键技术解析

1. 项目概述:IT资产管理为何需要全生命周期视角IT资产管理(IT Asset Management,简称ITAM)从来都不是简单的设备登记表。在我经手的十几个企业IT治理项目中,真正能把资产台账理清楚的团队不到三成。某次审计时发现&…

2026/10/15 7:08:16

TypeSafe Jev:从编译期到运行时的类型安全全链路实践

1. 从标题说起:TypeSafe Jev 到底在解决什么问题第一次看到“TypeSafe Jev”这个组合词,很多人会愣一下——TypeSafe 是类型安全,Jev 又是什么?这两个词拼在一起,指向的其实是一个很具体的工程痛点:在数据系…

2026/10/15 7:08:16

基于Python的网络爬虫系统设计与实现——毕业设计完整指南

1. 选题拆解:为什么“爬虫Python”是毕业设计的黄金组合每年毕业季,总有大量同学在选题阶段反复纠结。我见过太多人选了偏理论的方向,吭哧吭哧读了一堆论文,最后代码写不出来、实验数据凑不齐;也见过选纯前端、纯业务系…

2026/10/15 7:03:16

IQ测试题深度拆解:60题五大题型解析与刷题指南

简介:面向备考平安集团PA基础性向测试及同类智力测验的求职者,这份doc文档系统收录了60道经典IQ测试题与完整答案,覆盖类比推理、数字序列、逻辑推断、数学计算、词语解码等高频考点,并搭配逐题知识点详解,能帮助读者快…

2026/10/14 11:31:03

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/14 17:41:07

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/14 2:32:55

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/15 0:02:22

防关联浏览器哪个好?三款产品实测差异解析

新手做多店铺,最纠结的就是防关联浏览器选哪个。飞跨、网易、站斧这三款被问得最多,先给结论:要一体化省心、长期便宜,选站斧;要网易招牌和稳,选网易;预算紧做东南亚 Lazada,选飞跨。…

2026/10/15 0:02:22

影刀RPA深度实战:大模型Fine-tuning定制RPA专用Prompt与指令生成

影刀RPA深度实战:大模型Fine-tuning定制RPA专用Prompt与指令生成 一、技术背景 大模型(LLM)在通用场景下表现强大,但当我们将 GPT-4 或 Qwen 直接用于生成影刀RPA操作指令和 XPath 定位时,准确率通常只有 40%-60%。原因…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑