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