谷歌数据竞争检测工具ThreadSanitizer代码阅读记录——mutex相关文件

这篇博客详细介绍了ThreadSanitizer中不同类型的mutex,包括StaticSpinMutex、SpinMutex、BlockingMutex、RWMutex的实现原理,特别是Lock()和Unlock()的细节。还探讨了template类GenericScopedLock和GenericScopedReadLock的应用,以及MutexType枚举和Backoff类在锁算法中的作用。
摘要由CSDN通过智能技术生成

gcc-9.1.0\libsanitizer\sanitizer_common\sanitizer_mutex.h

这个文件一共定义了四个基本的类,分别是:

1. class StaticSpinMutex

StaticSpinMutex类拥有一个无符号型8位原子性字段:state_,1表示上锁,0表示空闲。显然这个变量是用于记录锁的状态的

成员函数主要为:Init(), Lock(), TryLock(), Unlock(), CheckLocked()五个,均使用Sanitizer Atomic中提到的原子操作实现。唯一复杂一点的函数是Lock(),代码如下:

 void Lock() {
   
    if (TryLock())
      return;
    LockSlow();
  }
  
 bool TryLock() {
   
    return atomic_exchange(&state_, 1, memory_order_acquire) == 0;
  }
 
 void NOINLINE LockSlow() {
   
    for (int i = 0;; i++) {
   
      if (i < 10)
        proc_yield(10);
      else
        internal_sched_yield();
      if (atomic_load(&state_, memory_order_relaxed) == 0
          && atomic_exchange(&state_, 1, memory_order_acquire) == 0)
        return;
    }
  }

Lock() 函数首先调用了 TryLock() 获取锁,当锁正忙时,就启用 LockSlow() ,LockSlow() 函数通过循环挂起不断尝试获取锁,一共分两步:

  1. 调用了两个相似的函数 proc_yield 和 internal_sched_yield,我个人理解的是 proc_yield 是一种假的挂起,调用这个函数不会将当前进程交换出执行队列,而 internal_sched_yield 是真的将该进程换出执行队列让出CPU,等待下次被调度放入CPU执行。就像一个公共厕所,我第一次到的时候首先试着等了10分钟,结果一直有人用,于是我先回到自己的座位,休息会儿又来看一眼还有没有人用,发现还有人用,于是回去接着等会再来,不断循环直到开始使用公厕。

  2. 通过atomic_load(),检查当前锁是否空闲,然后通过atomic_exchange获得锁的使用权,只有当都成功以后,才表示成功获得锁。

2. class SpinMutex : public StaticSpinMutex

包括三个函数:一个默认构造函数,一个拷贝构造函数和一个运算符“=”重载函数

3. class BlockingMutex

首先这个类的构造函数声明如下:

  explicit constexpr BlockingMutex(LinkerInitialized)
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值