线程安全注解是现代C++开发的机制,可以在代码编译阶段检查锁的使用情况,从而发现线程同步的相关问题。
1. 线程安全注解的使用
按照clang的线程安全注解文档 可以看到如果需要使用线程安全注解的相关功能需要对锁进行相关的封装之后才可以进行使用。目前存在clang存在两套线程安全注解的使用方法,本文仅介绍最新的线程安全注解使用方式(新的capability机制已经完全取代了之前的lockable机制)。
在使用前,首先了解一下clang官方推荐的mutex.h中实现的几个宏
CAPABILITY//该宏负责指定相关的类使用线程安全检测机制,即标准文档所说的功能,用于直接修饰类
SCOPED_CAPABILITY//负责实现RAII样式锁定的类属性,即在构造时获取能力,析构时释放能力。其他和CAPABILITY类似。
GUARDED_BY //声明数据成员受给定功能保护。对数据的读取操作需要共享访问,而写入操作需要独占访问。
PT_GUARDED_BY和GUARDED_BY类似,用于指针和智能指针,用户保护指针指向的数据。
ACQUIRED_BEFORE需要在另一个能力获取之前被调用
ACQUIRED_AFTER需要在另一个能力获取之后被调用
REQUIRES用来修饰函数,使其调用线程必须具有对给定功能的独占访问权限。被修饰的函数在进入前必须已经持有能力,函数退出时不在持有能力。
这个变量的概念比较绕,实际上转化为代码之后,比较好理解,下面时clang提供的官方代码
Mutex mu1, mu2;
int a GUARDED_BY(mu1);
int b GUARDED_BY(mu2);
void foo() REQUIRES(mu1, mu2) {
a = 0;
b = 0;
}
void test() {
mu1.Lock();
foo();