资讯详情

资讯详情

《C++ 并发编程指南》互斥量与锁专题:`<mutex>` 头文件摘要全景解析

教程并发编程【免费下载链接】Cplusplus-Concurrency-In-PracticeA Detailed Cplusplus Concurrency Tutorial 《C 并发编程指南》项目地址https://gitcode.com/gh_mirrors/cp/Cplusplus-Concurrency-In-Practice点击查看免费下载本文是《C 并发编程指南》第四章「互斥量与锁」的开篇导读以仓库文档 4.1mutex头文件摘要 为核心骨架对 C11 标准mutex头文件中声明的全部组件做一次全景梳理四种互斥量std::mutex、std::recursive_mutex、std::timed_mutex、std::recursive_timed_mutex、两种 RAII 锁类型std::lock_guard、std::unique_lock、三种 Tag 标记类型、std::once_flag以及std::lock、std::try_lock、std::call_once三个辅助函数并逐一给出标准类摘要class synopsis。读完本文你将建立起 C11 互斥量与锁的完整类型地图清楚每一种类型「能做什么、不能做什么、在什么场景下选用」为后续阅读互斥量详解、锁类型详解并动手编写多线程同步代码打好基础。1. 为什么必须包含mutex头文件Mutex 又称互斥量。C11 中与 Mutex 相关的类包括锁类型和函数都声明在mutex头文件中所以如果你在程序里面使用std::mutex及相关类型和辅助函数就必须包含mutex头文件#include mutex这一条和std::thread需要包含thread、std::atomic需要包含atomic是同一套组织方式C11 将并发设施按头文件分门别类。以本仓库 code/chapter1/hello-world/hello-world.cc 为例它使用std::thread时同样在开头包含了thread头文件。凡是要在代码里使用互斥量上锁/解锁、用 RAII 锁管理临界区、或者用call_once保证函数只被调用一次第一步都是引入mutex。2. C11 中定义的与互斥量和锁相关的类总览C11 标准在mutex头文件中定义了几大类与互斥量和锁相关的组件下面先建立整体认知第 3、4 节再给出精确的声明摘要。2.1 Mutex 系列类四种C11 标准中规定的与互斥量相关的类共有四种std::mutex最基本的 Mutex 类提供了最基本的上锁和解锁操作。基本的互斥量不允许某个线程在已获得互斥量的情况下重复对该互斥量进行上锁操作所以重复上锁将会导致死锁结果通常是未定义的。std::recursive_mutex递归 Mutex 类与std::mutex功能基本相同但是允许互斥量的拥有者通常是某个线程重复对该互斥量进行上锁操作而不会产生死锁但必须保证上锁和解锁的次数相同。std::timed_mutex定时 Mutex 类与std::mutex功能基本相同但是提供了两个额外的定时上锁操作try_lock_for和try_lock_until。即某个线程在规定的时间内对互斥量进行上锁操作如果在规定的时间内获得了锁则返回true超时则返回false。std::recursive_timed_mutex定时递归 Mutex 类既提供了重复上锁功能又提供了定时上锁的特性即在规定的时间内没有获得锁则返回false相当于std::recursive_mutex和std::timed_mutex的组合。说明标准库类型名以std::timed_mutex为准部分资料中也写作std::time_mutex下文统一使用标准名std::timed_mutex。四种互斥量之间的能力差异可以归纳为一张对比表类型重复上锁递归定时上锁try_lock_for / try_lock_until典型场景std::mutex不支持重复上锁导致死锁不支持通用临界区保护std::recursive_mutex支持lock/unlock 次数需配对不支持递归函数内多次获取同一把锁std::timed_mutex不支持支持需要限时等待锁、避免无限阻塞std::recursive_timed_mutex支持支持既递归又限时的复合场景try_lock_for与try_lock_until之间存在着细微差异前者接收一个相对时间长度chrono::duration表示「从调用时刻起在这段时间内尝试获得锁」后者接收一个绝对时间点chrono::time_point表示「在指定时间点到来之前尝试获得锁」。std::timed_mutex类摘要中两者的模板签名也印证了这一点——try_lock_for的参数类型是chrono::durationRep, Periodtry_lock_until的参数类型是chrono::time_pointClock, Duration。2.2 Lock 类两种C11 标准中定义了两种与互斥量相关的 RAII 技术。RAII 即 Resource Acquisition Is Initialization资源获取即初始化把资源的获取与对象的生命周期绑定对象构造时获取资源、对象析构时释放资源从而保证资源这里指锁在异常路径下也能被正确释放。std::lock_guard与 Mutex RAII 相关方便线程对互斥量上锁。std::unique_lock与 Mutex RAII 相关方便线程对互斥量上锁但提供了更好的上锁和解锁控制。lock_guard的特点是简单安全unique_lock则在 RAII 的基础上提供了更灵活的控制延迟上锁、定时上锁、手动解锁、移动所有权、release()等。两者的详细用法与构造函数分析见仓库 4.3 锁类型详解。2.3 其他类型mutex头文件中还包含以下辅助类型std::once_flagcall_once辅助函数会使用到该类型的对象。std::adopt_lock_t一个空的标记类定义如下struct adopt_lock_t {};。该类型的常量对象adopt_lockadopt_lock是一个常量对象定义如下constexpr adopt_lock_t adopt_lock {};constexpr是 C11 中的新关键字通常作为参数传入给unique_lock或lock_guard的构造函数表示「互斥量已经被当前线程锁住请接管adopt它」。std::defer_lock_t一个空的标记类定义如下struct defer_lock_t {};。该类型的常量对象defer_lock定义如下constexpr defer_lock_t defer_lock {};通常作为参数传入给unique_lock或lock_guard的构造函数表示「先不立即上锁推迟defer上锁时机」。std::try_to_lock_t一个空的标记类定义如下struct try_to_lock_t {};。该类型的常量对象try_to_lock定义如下constexpr try_to_lock_t try_to_lock {};通常作为参数传入给unique_lock或lock_guard的构造函数表示「尝试try上锁失败时不阻塞」。这三个 Tag 类型都是「空的标记类」它们的存在价值不是携带数据而是通过「重载选择」告诉锁类型的构造函数以何种策略管理互斥量。adopt_lock、defer_lock、try_to_lock是 C11 标准库预定义的constexpr常量对象可以直接作为实参传入。2.4 辅助函数mutex头文件中还声明了三个自由函数非成员函数std::try_lock尝试同时对多个互斥量上锁。std::lock同时对多个互斥量上锁。std::call_once如果多个线程需要同时调用某个函数call_once可以保证多个线程对该函数只调用一次。其中std::lock与std::try_lock用于解决「一次锁定多个互斥量」时的死锁风险如果分别对两个互斥量逐个lock()两个线程以相反顺序上锁就可能产生死锁而std::lock内部会以「同时锁定、失败则回退」的算法避免这一问题详见仓库 4.3 锁类型详解 中task_a/task_b的示例。std::call_once与std::once_flag配合使用是 C11 中实现「线程安全的懒初始化lazy initialization」的推荐手段。3.mutex头文件摘要本章后面会对以上类型和函数进行详细介绍我们首先来看mutex头文件中各个类型的摘要synopsis。所谓「摘要」是标准中给出的类接口清单——只声明成员函数签名不包含实现细节作用是精确刻画「这个类型对外提供哪些操作、哪些操作被禁止」。完整的mutex头文件摘要如下namespace std { class mutex; class recursive_mutex; class timed_mutex; class recursive_timed_mutex; struct defer_lock_t { }; struct try_to_lock_t { }; struct adopt_lock_t { }; constexpr defer_lock_t defer_lock { }; constexpr try_to_lock_t try_to_lock { }; constexpr adopt_lock_t adopt_lock { }; template class Mutex class lock_guard; template class Mutex class unique_lock; template class Mutex void swap(unique_lockMutex x, unique_lockMutex y); template class L1, class L2, class... L3 int try_lock(L1, L2, L3...); template class L1, class L2, class... L3 void lock(L1, L2, L3...); struct once_flag { constexpr once_flag() noexcept; once_flag(const once_flag) delete; once_flag operator(const once_flag) delete; }; templateclass Callable, class ...Args void call_once(once_flag flag, Callable func, Args... args); }从这份摘要中可以读出几个重要信息四种互斥量类mutex、recursive_mutex、timed_mutex、recursive_timed_mutex在头文件层面先做前置声明具体接口在各自类摘要中给出三个 Tag 结构与三个constexpr常量对象一一对应defer_lock_t/defer_lock、try_to_lock_t/try_to_lock、adopt_lock_t/adopt_lock两种锁类型都是类模板template class Mutex class lock_guard;与template class Mutex class unique_lock;模板参数Mutex即被管理的互斥量类型std::swap被特化为unique_lockMutex提供了非成员swap重载std::lock/std::try_lock是可变参数模板class... L3可以一次处理任意多个锁对象once_flag不可拷贝拷贝构造与拷贝赋值均被 delete并且拥有constexpr默认构造这保证了once_flag可以作为静态存储期对象使用。4. 各类摘要详解4.1std::mutex类摘要std::mutex是 C11 中最基本的互斥量提供独占所有权特性——不支持递归地对std::mutex对象上锁。其类摘要如下namespace std { class mutex { public: constexpr mutex(); ~mutex(); mutex(const mutex) delete; mutex operator(const mutex) delete; void lock(); bool try_lock() noexcept; void unlock() noexcept; typedef implementation-defined native_handle_type; native_handle_type native_handle(); }; }对摘要中每个声明的解读constexpr mutex();默认构造函数新创建的mutex对象处于 unlocked未上锁状态constexpr修饰意味着它可以用于常量表达式上下文例如全局/静态对象的常量初始化。~mutex();析构函数。注意标准要求析构时互斥量必须处于未上锁状态否则行为未定义。mutex(const mutex) delete;与mutex operator(const mutex) delete;拷贝构造与拷贝赋值被显式删除。互斥量不能拷贝、不能赋值——这是所有四种互斥量共有的设计因为「锁的所有权」语义上不可复制。void lock();上锁。调用线程将锁住该互斥量调用时可能发生三种情况(1) 如果该互斥量当前没有被锁住则调用线程将该互斥量锁住直到调用unlock之前该线程一直拥有该锁(2) 如果当前互斥量被其他线程锁住则当前的调用线程被阻塞住(3) 如果当前互斥量被当前调用线程锁住则会产生死锁deadlock。bool try_lock() noexcept;尝试锁住互斥量如果互斥量被其他线程占有则当前线程也不会被阻塞。调用时同样可能出现三种情况(1) 如果当前互斥量没有被其他线程占有则该线程锁住互斥量直到调用unlock释放(2) 如果当前互斥量被其他线程锁住则当前调用线程返回false而并不会被阻塞(3) 如果当前互斥量被当前调用线程锁住则会产生死锁。void unlock() noexcept;解锁释放对互斥量的所有权。typedef implementation-defined native_handle_type;与native_handle()返回由实现定义的「原生句柄」类型。在不同平台上它对应底层线程库的互斥量句柄例如 POSIX 平台上的pthread_mutex_t*用于与平台特定的底层 API 交互。std::mutex与 POSIXpthread_mutex_t的编程接口差异仓库在 4.5 小节 中有专题对比。4.2std::recursive_mutex类摘要std::recursive_mutex与std::mutex一样也是一种可以被上锁的对象区别在于它允许同一个线程对互斥量多次上锁即递归上锁从而获得对互斥量对象的多层所有权。释放互斥量时需要调用与该锁层次深度相同次数的unlock()可理解为lock()次数和unlock()次数相同。除此之外std::recursive_mutex的特性和std::mutex大致相同。其类摘要如下namespace std { class recursive_mutex { public: recursive_mutex(); ~recursive_mutex(); recursive_mutex(const recursive_mutex) delete; recursive_mutex operator(const recursive_mutex) delete; void lock(); bool try_lock() noexcept; void unlock() noexcept; typedef implementation-defined native_handle_type; native_handle_type native_handle(); }; }对比std::mutex的摘要可以看到recursive_mutex的接口形态几乎完全一致lock/try_lock/unlock/native_handle唯一的显著差异是默认构造函数不再是constexpr。语义层面的差异允许递归上锁由标准库实现内部维护「锁层次深度」来保证并不反映在接口签名上。4.3std::timed_mutex类摘要std::timed_mutex比std::mutex多了两个成员函数try_lock_for()和try_lock_until()。其类摘要如下namespace std { class timed_mutex { public: timed_mutex(); ~timed_mutex(); timed_mutex(const timed_mutex) delete; timed_mutex operator(const timed_mutex) delete; void lock(); bool try_lock(); template class Rep, class Period bool try_lock_for(const chrono::durationRep, Period rel_time) noexcept; template class Clock, class Duration bool try_lock_until(const chrono::time_pointClock, Duration abs_time) noexcept; void unlock(); typedef implementation-defined native_handle_type; native_handle_type native_handle(); }; }两个新增成员函数的语义try_lock_for(rel_time)接受一个时间范围chrono::duration表示在这段时间范围之内线程如果没有获得锁则被阻塞住。这与std::mutex的try_lock()不同——try_lock如果被调用时没有获得锁则直接返回false而try_lock_for会阻塞等待一段时间。如果在此期间其他线程释放了锁则该线程可以获得对互斥量的锁如果超时即在指定时间内还是没有获得锁则返回false。try_lock_until(abs_time)接受一个时间点chrono::time_point作为参数在指定时间点未到来之前线程如果没有获得锁则被阻塞住。如果在此期间其他线程释放了锁则该线程可以获得对互斥量的锁如果超时即在指定时间内还是没有获得锁则返回false。二者的差异总结try_lock_for用「相对时长」表达等待上限适合「等 200 毫秒」这类需求try_lock_until用「绝对时间点」表达截止时刻适合「等到某个时刻为止」这类需求例如与steady_clock::now()计算出的截止点配合。注意timed_mutex::try_lock()与try_lock_for/try_lock_until均声明为noexcept而上锁失败时lock()会抛出system_error。4.4std::recursive_timed_mutex类摘要和std::recursive_mutex与std::mutex的关系一样std::recursive_timed_mutex的特性可以从std::timed_mutex推导出来它同时具备「递归上锁」与「定时上锁」两种能力相当于std::recursive_mutex与std::timed_mutex的组合。其类摘要如下namespace std { class recursive_timed_mutex { public: recursive_timed_mutex(); ~recursive_timed_mutex(); recursive_timed_mutex(const recursive_timed_mutex) delete; recursive_timed_mutex operator(const recursive_timed_mutex) delete; void lock(); bool try_lock(); template class Rep, class Period bool try_lock_for(const chrono::durationRep, Period rel_time) noexcept; template class Clock, class Duration bool try_lock_until(const chrono::time_pointClock, Duration abs_time) noexcept; void unlock(); typedef implementation-defined native_handle_type; native_handle_type native_handle(); }; }接口形态与std::timed_mutex完全一致lock/try_lock/try_lock_for/try_lock_until/unlock/native_handle语义上额外叠加了递归特性——同一线程可多次上锁且解锁次数必须与上锁次数匹配。4.5std::lock_guard类摘要std::lock_guard是 C11 中定义的模板类template class Mutex class lock_guard;。lock_guard对象通常用于管理某个锁Lock对象与 Mutex RAII 相关方便线程对互斥量上锁在某个lock_guard对象的生命周期内它所管理的锁对象会一直保持上锁状态而lock_guard的生命周期结束之后它所管理的锁对象会被解锁类似shared_ptr等智能指针管理动态分配的内存资源。lock_guard对象并不负责管理 Mutex 对象的生命周期它只简化上锁与解锁操作。其类摘要如下namespace std { template class Mutex class lock_guard { public: typedef Mutex mutex_type; explicit lock_guard(mutex_type m); lock_guard(mutex_type m, adopt_lock_t) noexcept; ~lock_guard(); lock_guard(lock_guard const) delete; lock_guard operator(lock_guard const) delete; private: mutex_type pm; // exposition only }; }摘要解读typedef Mutex mutex_type;将模板参数Mutex暴露为嵌套类型mutex_type便于泛型代码引用。explicit lock_guard(mutex_type m);locking 构造。lock_guard对象管理 Mutex 对象m并在构造时对m进行上锁调用m.lock()。lock_guard(mutex_type m, adopt_lock_t) noexcept;adopting 构造。lock_guard对象管理 Mutex 对象m与 locking 构造不同的是此时 Mutex 对象m已被当前线程锁住通过std::adopt_lock标记告知构造函数「锁已经拿到直接接管」。典型的配合写法是先mtx.lock()再std::lock_guardstd::mutex lck(mtx, std::adopt_lock);。~lock_guard();析构时自动对它所管理的 Mutex 对象调用unlock()。正是这一行为保证了「异常抛出时锁也能被正确释放」——局部lock_guard对象在栈展开stack unwinding过程中析构锁随之释放。拷贝构造与拷贝赋值均被 deletelock_guard对象不可拷贝、不可移动所有权不可转让。私有成员mutex_type pm;标注为// exposition only它只是「说明性成员」标准并不要求实现真正拥有该数据成员只要求行为等价。模板参数Mutex代表互斥量类型如std::mutex它应该是一个基本的BasicLockable类型只需满足两种操作lock和unlock。标准库中std::mutex、std::recursive_mutex、std::timed_mutex、std::recursive_timed_mutex以及std::unique_lock均满足BasicLockable。4.6std::unique_lock类摘要lock_guard最大的特点是安全简单但最大的缺点也是简单——没有给程序员提供足够的灵活度。因此 C11 标准中定义了另外一个与 Mutex RAII 相关的类unique_lock它同样方便线程对互斥量上锁但提供了更好的上锁和解锁控制。顾名思义unique_lock对象以独占所有权的方式unique ownership管理 mutex 对象的上锁和解锁操作——所谓独占所有权就是没有其他的unique_lock对象同时拥有某个 mutex 对象的所有权。其类摘要如下namespace std { template class Mutex class unique_lock { public: typedef Mutex mutex_type; // 构造/拷贝/析构: unique_lock() noexcept; explicit unique_lock(mutex_type m); unique_lock(mutex_type m, defer_lock_t) noexcept; unique_lock(mutex_type m, try_to_lock_t) noexcept; unique_lock(mutex_type m, adopt_lock_t) noexcept; template class Clock, class Duration unique_lock(mutex_type m, const chrono::time_pointClock, Duration abs_time) noexcept; template class Rep, class Period unique_lock(mutex_type m, const chrono::durationRep, Period rel_time) noexcept; ~unique_lock(); unique_lock(unique_lock const) delete; unique_lock operator(unique_lock const) delete; unique_lock(unique_lock u) noexcept; unique_lock operator(unique_lock u) noexcept; // 上锁操作: void lock(); bool try_lock(); template class Rep, class Period bool try_lock_for(const chrono::durationRep, Period rel_time); template class Clock, class Duration bool try_lock_until(const chrono::time_pointClock, Duration abs_time); void unlock(); // 修改操作 void swap(unique_lock u) noexcept; mutex_type *release() noexcept; // observers: bool owns_lock() const noexcept; explicit operator bool () const noexcept; mutex_type* mutex() const noexcept; private: mutex_type *pm; // exposition only bool owns; // exposition only }; template class Mutex void swap(unique_lockMutex x, unique_lockMutex y) noexcept; }摘要解读——unique_lock相比lock_guard的灵活性体现在三个层面构造方式多样除了默认构造和 locking 构造还提供了四种带 Tag/时间参数的构造——defer_lock_t延迟上锁构造时不锁、try_to_lock_t尝试上锁失败不阻塞、adopt_lock_t接管已持有的锁、chrono::duration/chrono::time_point定时上锁。默认构造的unique_lock不管理任何 Mutex 对象通过 adopting 或 locking 构造的对象通常拥有锁通过 deferred 构造的对象不拥有锁通过 try-locking 和定时构造的对象则在lock成功时获得锁。支持移动语义拷贝构造与拷贝赋值被删除但移动构造与移动赋值可用unique_lock(unique_lock u) noexcept等。移动之后被移动的对象如同默认构造的一样不再管理任何 Mutex。提供完整的成员函数集上锁/解锁操作lock、try_lock、try_lock_for、try_lock_until、unlock修改操作移动赋值、swap与另一个unique_lock交换所管理的 Mutex 对象的所有权、release返回指向所管理的 Mutex 对象的指针并释放所有权观察操作owns_lock返回当前对象是否获得了锁、operator bool与owns_lock功能相同、mutex返回所管理的 Mutex 对象的指针。私有成员pmmutex_type*与ownsbool同样标注为// exposition only标准只要求行为等价——用指针记录管理的互斥量、用布尔值记录当前是否持有锁。std::unique_lock与std::lock_guard一样也保证在其自身析构时它所管理的 Mutex 对象能够被正确解锁即使没有显式调用unlock函数因此也是一种简单而安全的上锁和解锁方式尤其适合在程序抛出异常后保证先前已被上锁的 Mutex 对象被正确解锁。它的模板参数Mutex同样是BasicLockable类型。各类构造函数的逐一分析与完整示例见仓库 4.3 锁类型详解。5. 从摘要中读出的关键设计把第 3、4 节的摘要放在一起对照可以总结出mutex头文件的几个贯穿性设计原则1互斥量不可拷贝、不可赋值。四种互斥量类的拷贝构造与拷贝赋值全部被 delete。这是互斥量语义的必然要求锁的所有权无法复制否则将出现「两份所有权」的未定义状态。同理once_flag也不可拷贝。2RAII 锁类型接管「解锁」责任。lock_guard与unique_lock都在析构时自动解锁将「手动 lock/unlock 配对」的繁琐且易错的操作收敛为「对象生命周期即临界区」的模型。两种锁都不负责管理 Mutex 对象的生命周期Mutex 由用户自行创建和持有只负责上锁/解锁操作。3Tag 类型驱动「构造策略」。defer_lock、try_to_lock、adopt_lock三个空标记类与常量对象通过构造函数重载让同一套 RAII 框架支持「延迟上锁」「尝试上锁」「接管已持有的锁」三种策略这是 C 中「空类型 重载」这一惯用法的典型体现。4互斥量能力分层BasicLockable→Lockable→TimedLockable。从摘要可以清晰看到能力递增的三层概念BasicLockable只需支持lock和unlock四种互斥量与unique_lock均满足Lockable在BasicLockable基础上新增try_lockstd::mutex、std::recursive_mutex满足TimedLockable在Lockable基础上再新增try_lock_for和try_lock_untilstd::timed_mutex、std::recursive_timed_mutex满足。这种分层正是模板算法如std::lock能够同时作用于多种锁对象的原因。5constexpr与noexcept的运用。mutex的默认构造函数、三个 Tag 常量对象、once_flag的默认构造函数都是constexpr支持常量初始化try_lock、unlock、try_lock_for、try_lock_until等非阻塞类操作声明为noexcept而可能阻塞或失败的lock()在失败时抛出system_error。这些细节在阅读摘要时值得留意它们直接影响代码能否用于常量表达式上下文以及异常处理策略。6. 在仓库环境中编译与验证理解了类型摘要之后下一步就是在真实环境中编译运行。本仓库虽然目前只包含一个可直接编译的示例 code/chapter1/hello-world/hello-world.ccstd::thread的 hello world但它的 Makefile 明确给出了本书全部并发示例的统一编译方式CCg CPPFLAGS-Wall -stdc11 -ggdb LDFLAGS-pthread要点解读-stdc11必须启用 C11 标准或更高版本mutex头文件与std::mutex等类型仅在 C11 及之后的语言标准中可用-pthread链接 POSIX 线程库。在 Linux 平台下凡使用std::thread、std::mutex等并发设施的程序编译和链接阶段都需要该选项编译期定义_REENTRANT等宏链接期引入libpthread-Wall -ggdb开启全部警告与调试信息便于排查并发代码中常见的未使用变量、隐式转换等问题。参照该 Makefile编译一个包含mutex的程序可以简化为g -stdc11 -pthread -o mutex_demo mutex_demo.cc需要注意的是Makefile 中的-stdc11意味着仓库示例面向 C11 标准编写如果你的编译环境默认标准更高如 C17/C20mutex头文件中的接口会兼容扩展但本文描述的类摘要仍以 C11 为基准。7. 后续学习路径本文是第四章的开篇只完成了「类型地图」的构建。mutex头文件中各类的具体用法、完整可运行的代码示例以及更深入的话题在仓库中按以下顺序展开4.1mutex头文件摘要本文对应的原始文档4.2 互斥量详解std::mutex的try_lock示例、std::recursive_mutex的递归上锁示例、std::timed_mutex的try_lock_for「烟花fireworks」示例等4.3 锁类型详解lock_guard与unique_lock的全部构造函数、移动赋值、各成员函数lock/try_lock/try_lock_for/try_lock_until/unlock/release/owns_lock/operator bool/mutex的逐一分析与示例以及利用std::lock(foo, bar)同时锁定多把互斥量避免死锁的经典写法本章导读 README.md第四章整体内容规划web-resources.md与互斥量、锁相关的延伸阅读资料清单。掌握mutex头文件的类型全景之后建议按「互斥量详解 → 锁类型详解 → 条件变量第五章」的顺序继续深入最终形成完整的 C11 线程同步知识体系。赞分享教程并发编程【免费下载链接】Cplusplus-Concurrency-In-PracticeA Detailed Cplusplus Concurrency Tutorial 《C 并发编程指南》项目地址https://gitcode.com/gh_mirrors/cp/Cplusplus-Concurrency-In-Practice点击查看免费下载相关推荐如何快速构建智能聊天机器人使用 gemma-4-E4B-it-MLX-4bit 的完整实战指南如何快速构建智能聊天机器人使用 gemma 4 E4B it MLX 4bit 的完整实战指南 想要构建一个高效智能的聊天机器人吗gemma 4 E4B iC并发编程实战深入理解mutex头文件C并发编程实战深入理解 mutex 头文件 前言 在多线程编程中互斥量 Mutex 是最基础的同步机制之一。C11标准库中的 mutex 头文件文档教程comprehensive-rust 并发编程系列深入解析 std::sync::Mutex 互斥锁与共享可变状态comprehensive rust 并发编程系列深入解析 std::sync::Mutex 互斥锁与共享可变状态 本篇技术指南以 Google Androi文档教程上一篇远程系统资源监控基于Quasar的实时数据采集技术下一篇ECS集群安全更新策略AMI更新与实例替换最佳实践指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →