C++对象级锁:独立加锁实现持不同S对象的P对象并行
结论前置
完全可以实现对S1、S2的独立分离加锁,持有不同S实例引用的P类对象能够无冲突并行执行业务逻辑。
实现原理说明
C本身没有语言层面内置的对象头锁,大家常说的C对象级锁机制,本质是开发者通过把互斥量声明为类的非静态成员,让每个类实例自带独立锁的实现方式,核心特征是锁的作用域和具体类实例绑定,而非和类本身绑定:
- 只要锁对象是S类的非静态成员,每一个新创建的S类实例,都会拥有一份完全独立的锁副本,不存在跨实例的锁共享。
- 对应到本场景中,S1、S2是两个独立的S类实例,天然各自持有独立的锁:持有S1引用的10个P对象,在执行业务时只会竞争S1自身的锁;持有S2引用的10个P对象,只会竞争S2自身的锁。两类操作之间不存在任何锁竞争,系统调度层面完全可以让两个分属不同锁的临界区并行执行。
常见实现误区
要达到这个并行效果,需要避开几个容易踩的坑:
- 不要将锁声明为S类的静态成员:静态成员属于类本身而非单个实例,会导致所有S实例共享同一把锁,此时无论操作S1还是S2,都会被同一把锁串行阻塞,无法并行。
- 不要在P类的业务逻辑中加全局/类级共享锁:如果P的业务逻辑被P类的静态锁、全局互斥量包裹,不管P持有的是哪个S实例的引用,所有P的业务执行都会被串行化,完全失去并行能力。
- 合理控制临界区范围:锁只需要包裹对对应S实例的读写操作即可,不要将和当前S实例无关的计算、IO逻辑放进临界区,避免不必要的性能损耗。
参考实现代码
#include <mutex> class S { private: // 非静态成员,每个S实例独立持有一把锁 std::mutex own_lock; public: void run_instance_biz() { // 加当前实例自己的锁,保护实例内部数据 std::lock_guard<std::mutex> lock(own_lock); // 该实例的具体业务逻辑 } }; class P { private: S& bound_s; public: P(S& s) : bound_s(s) {} void run_p_biz() { // 直接调用持有的S实例的业务方法,自动绑定对应实例的锁 bound_s.run_instance_biz(); } };
代码执行效果:持有S1引用的P对象执行
run_p_biz()时,锁定的是S1内部的own_lock;持有S2引用的P对象执行同方法时,锁定的是S2内部的own_lock。两个锁完全独立,不存在竞争,可并行执行。
内容的提问来源于stack exchange,提问作者Arpit Gupta
相关产品推荐
相关产品推荐

