android mutex 详细介绍

在多线程的Android环境中,Mutex作为同步工具防止全局变量的并发访问。它本质上是对pthread_mutex_xxx()接口的封装,涉及到的源文件包括CameraBase.h、Mutex.h以及pthread_mutex.cpp等。当线程尝试获取锁失败时,会进入等待状态,通过__pthread_mutex_lock_with_timeout()处理。解锁操作由pthread_mutex_unlock()完成,而销毁Mutex则通过pthread_mutex_destroy()函数执行。
摘要由CSDN通过智能技术生成

一个进程中不可能只有一个线程在战斗,所以一个进程中一般都是有多个线程的同时协助工作,多线程情况下,对于一些全局变量,也就是多个线程能够同时访问的变量,我们需要通过加锁来防止“同时”访问这个变量,Mutex 就是我们常用的一个。

frameworks/av/include/camera/CameraBase.h

113      Mutex                            mLock;
frameworks/av/camera/Camera.cpp

214  void Camera::stopRecording()
215  {
216      ALOGV("stopRecording");
217      {
218          Mutex::Autolock _l(mLock);
219          mRecordingProxyListener.clear();
220      }
221      sp <::android::hardware::ICamera> c = mCamera;
222      if (c == 0) return;
223      c->stopRecording();
224  }
例如上面的代码,首先会定义一个Mutex 对象mLock,在代码中对全局变量访问时,先要获取mLock,例如上面在操作mRecordingProxyListener 时,先通过Mutex::Autolock _l(mLock);获取这把锁,加了大括号是限制这个锁的作用域,离开这个作用域之后,这把锁会自动释放,下面会介绍。

system/core/include/utils/Mutex.h

100   pthread_mutex_t mMutex;
111  inline Mutex::Mutex() {
112      pthread_mutex_init(&mMutex, NULL);
113  }

83      class Autolock {
84      public:
85          inline Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); }
86          inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
87          inline ~Autolock() { mLock.unlock(); }
88      private:
89          Mutex& mLock;
90      };

131  inline status_t Mutex::lock() {
132      return -pthread_mutex_lock(&mMutex);
133  }

134  inline void Mutex::unlock() {
135      pthread_mutex_unlock(&mMutex);
136  }

128  inline Mutex::~Mutex() {
129      pthread_mutex_destroy(&mMutex);
130  }
通过上面的代码我们知道 Mutex::Autolock _l(mLock) 获取锁和释放锁 是利用了C++ 类的构造函数和析构函数的特性实现的。在.h头文件里面定义 Mutex    mLock; 的时候就已经调用了Mutex   的构造函数,进而调用到pthread_mutex_init()初始化pthread_mutex_t mMutex;  而Mutex::Autolock _l(mLock); 放在函数里面定义,是一个局部变量,也会调用Autolock 的构造函数,进而调用到Mutex::lock();  Autolock 对象 _l 跑出大括号后,也就是跑出它的作用域后,会调用它的析构函数,进而调用到Mutex::unlock() 释放锁。

Mutex 只是对对pthread_mutex_xxx()接口做了一层封装而已,真正的实现在pthread_mutex_xxx()接口。
pthread_mutex_xxx()声明在bionic/libc/include/pthread.h

39  typedef struct {
40  #if defined(__LP64__)
41    int32_t __private[10];  //长度为10的整形数组
42  #else
43    int32_t __private[1];  //长度为1 的整形数组
44  #endif
45  } pthread_mutex_t;

1、初始化函数pthread_mutex_init()

 bionic/libc/bionic/pthread_mutex.cpp

241  int pthread_mutex_init(pthread_mutex_t* mutex_interface, const pthread_mutexattr_t* attr) {
/*
 *   struct pthread_mutex_internal_t {
 *    _Atomic(uint16_t) state;  //2 byte
 *  #if defined(__LP64__)  //64为定义是长度为10的整形数组, 40 byte
 *    uint16_t __pad;       //2 byte
 *    atomic_int owner_tid; //4 byte
 *    char __reserved[32];  //32 byte
 *  #else                  //长度为1 的整形数组, 4 byte
 *    _Atomic(uint16_t) owner_tid; //2 byte
 *  #endif
 *  } __attribute__((aligned(4)));
*/
242      pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);
243  
244      memset(mutex, 0, sizeof(pthread_mutex_internal_t));  //mutex 所有byte设置为 0
245  
246      if (__predict_true(attr == NULL)) {  //没有设置相关属性时
247          atomic_init(&mutex->state, MUTEX_TYPE_BITS_NORMAL);  //mutex->state = (((0) & ((1 << (2))-1)) << (14)) 也就是0
248          return 0;
249      }
...    //因为针对上面的实现传入的attr 为NULL,所以这部分的代码先不做分析
272      return 0;
273  }

2、获取锁函数pthread_mutex_lock()
bionic/libc/bionic/pthread_mutex.cpp
503  int pthread_mutex_lock(pthread_mutex_t* mutex_interface) {
504  #if !defined(__LP64__)  //非64为系统
505      if (mutex_interface == NULL) {
506          return EINVAL;
507      }
508  #endif
509  
510      pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);
511  
512      uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed); //old_state = mutex->state
513      uint16_t mtype = (old_state & MUTEX_TYPE_MASK);   //mtype =old_state &(((1 << (2))-1) << (14)) 也就是mtype =old_state & 49152
514      uint16_t shared = (old_state & MUTEX_SHARED_MASK);//shared =old_state &(((1 << (1))-1) << (13)) 也就是shared =old_state & 8192
515      // Avoid slowing down fast path of normal mutex lock operation.
516      if (__predict_true(mtype == MUTEX_TYPE_BITS_NORMAL)) {  //MUTEX_TYPE_BITS_NORMAL =0
517        if (__predict_true(__pthread_normal_mutex_trylock(mutex, shared) == 0)) {
518          return 0;  
519        }
520      }
521      return __pthread_mutex_lock_with_timeout(mutex, false, nullptr);
522  }
pthread_mutex_lock() 先判断 是否可以直接获取锁,没有其他线程在使用的时候可以获取,通过__pthread_normal_mutex_trylock()来实现


275  static inline __always_inline int __pthread_normal_mutex_trylock(pthread_mutex_internal_t* mutex,
276           
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值