android 高版本加入了c++2.0,和2.0+的标准库的一些东西,例如:std::thread,当然低版本使用还是Thread,不过他们都封装了pthread。
我在9.0的Thread源码中发现了如下一段话:
39// DO NOT USE: please use std::thread
40
41class Thread : virtual public RefBase
42{。。。。。。
可能是引入了c++2.0 or above的标准库的缘由,也可能是Thread.cpp/Mutex.cpp等的功能不如std::来的齐全,所以不推荐使用Thread类,推荐使用std::thread类,说法不正确的话,看到的朋友可以在评论区指出下。
android使用的实现库是llvm的libc++库,thread是一个class,看一下构造函数:
//std::thread in thread [no suffix] file
290 thread::thread(_Fp&& __f, _Args&&... __args)
291 {
292 typedef unique_ptr<__thread_struct> _TSPtr;
293 _TSPtr __tsp(new __thread_struct);
294 typedef tuple<_TSPtr, typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp;
295 _VSTD::unique_ptr<_Gp> __p(
296 new _Gp(std::move(__tsp),
297 __decay_copy(_VSTD::forward<_Fp>(__f)),
298 __decay_copy(_VSTD::forward<_Args>(__args))...));
299 int __ec = __libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get());
300 if (__ec == 0)
301 __p.release();
302 else
303 __throw_system_error(__ec, "thread constructor failed");
304 }
276 template
277 void* __thread_proxy(void* __vp)
278 {
279 // _Fp = std::tuple< unique_ptr<__thread_struct>, Functor, Args...>
280 std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
281 __thread_local_data().set_pointer(_VSTD::get<0>(*__p).release());
282 typedef typename __make_tuple_indices::value, 2>::type _Index;
283 __thread_execute(*__p, _Index());
284 return nullptr;
285 }
//__threading_support[no suffix]
333 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
334 void *__arg)
335 {
336 return pthread_create(__t, 0, __func, __arg);
337 }
最终调用到了pthread的pthread_create方法。
//std::mutex [mutex.cpp]
30 void
31 mutex::lock()
32 {
33 int ec = __libcpp_mutex_lock(&__m_);//!!!
34 if (ec)
35 __throw_system_error(ec, "mutex lock failed");
36 }
44 void
45 mutex::unlock() _NOEXCEPT
46 {
47 int ec = __libcpp_mutex_unlock(&__m_);//!!!
48 (void)ec;
49 _LIBCPP_ASSERT(ec == 0, "call to mutex::unlock failed");
50 }
//mutex_destructor.cpp
31 class _LIBCPP_TYPE_VIS mutex
32 {
33 __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER;//!!!
34
35 public:
36 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
37 constexpr mutex() = default;
38 mutex(const mutex&) = delete;
39 mutex& operator=(const mutex&) = delete;
40 ~mutex() noexcept;
41 };
42
43
44 mutex::~mutex() _NOEXCEPT
45 {
46 __libcpp_mutex_destroy(&__m_);//!!!
47 }
//__threading_support [no suffix]
57 typedef pthread_mutex_t __libcpp_mutex_t;//!!!
262 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
263 {
264 return pthread_mutex_lock(__m);//!!!
265 }
272 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
273 {
274 return pthread_mutex_unlock(__m);//!!!
275 }
277 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
278 {
279 return pthread_mutex_destroy(__m);//!!!
280 }
///bionic/libc/include/pthread.h
41enum {
42 PTHREAD_MUTEX_NORMAL = 0,
43 PTHREAD_MUTEX_RECURSIVE = 1,
44 PTHREAD_MUTEX_ERRORCHECK = 2,
45
46 PTHREAD_MUTEX_ERRORCHECK_NP = PTHREAD_MUTEX_ERRORCHECK,
47 PTHREAD_MUTEX_RECURSIVE_NP = PTHREAD_MUTEX_RECURSIVE,
48
49 PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
50};
52#define PTHREAD_MUTEX_INITIALIZER { { ((PTHREAD_MUTEX_NORMAL & 3) << 14) } }
std::mutex的lock(),unlock(),~mutex()也是通过_libcpp中转到了pthread_mutex_lock,pthread_mutex_unlock,pthread_mutex_destroy,让pthread承担起来。
其他的互斥体也是如此,不一一罗列。
/system/core/libutils/Threads.cpp
使用Thread,sp
/system/core/libutils/include/utils/Mutex.h
162inline Mutex::Mutex() {
163 pthread_mutex_init(&mMutex, NULL);
164}
165inline Mutex::Mutex(__attribute__((unused)) const char* name) {
166 pthread_mutex_init(&mMutex, NULL);
167}
168inline Mutex::Mutex(int type, __attribute__((unused)) const char* name) {
169 if (type == SHARED) {
170 pthread_mutexattr_t attr;
171 pthread_mutexattr_init(&attr);
172 pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
173 pthread_mutex_init(&mMutex, &attr);
174 pthread_mutexattr_destroy(&attr);
175 } else {
176 pthread_mutex_init(&mMutex, NULL);
177 }
178}
179inline Mutex::~Mutex() {
180 pthread_mutex_destroy(&mMutex);
181}
182inline status_t Mutex::lock() {
183 return -pthread_mutex_lock(&mMutex);
184}
185inline void Mutex::unlock() {
186 pthread_mutex_unlock(&mMutex);
187}
188inline status_t Mutex::tryLock() {
189 return -pthread_mutex_trylock(&mMutex);
190}
191#if defined(__ANDROID__)
192inline status_t Mutex::timedLock(nsecs_t timeoutNs) {
193 timeoutNs += systemTime(SYSTEM_TIME_REALTIME);
194 const struct timespec ts = {
195 /* .tv_sec = */ static_cast(timeoutNs / 1000000000),
196 /* .tv_nsec = */ static_cast(timeoutNs % 1000000000),
197 };
198 return -pthread_mutex_timedlock(&mMutex, &ts);
199}
200#endif
Mutex也是使用到了pthread。
std::和Thread这两项,都用到了pthread,可见pthread在android中的重要性。java中LockSupport的native使用的也是pthread.
其实pthread是我的叫法,它的正确叫法是Pthreads,POSIX Threads,是POSIX的线程标准,定义了创建和操纵线程的一套API。
标准就是指API,它是跨平台(os)的接口,android可能借用linux的Pthreads库,实现了这套标准。看来制定标准的都在想着要做老大。
锁类型有三种:1.MUTEX_TYPE_BITS_NORMAL普通锁,非其余两种,2.MUTEX_TYPE_BITS_RECURSIVE支持重入,3. MUTEX_TYPE_BITS_ERRORCHECK,支持错误检查。我们只看普通锁。
798int pthread_mutex_lock(pthread_mutex_t* mutex_interface) {
......
807
808 pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);
//原子load到state的字段值
809 uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
810 uint16_t mtype = (old_state & MUTEX_TYPE_MASK);
//避免减慢获取正常互斥锁的快速路径,TryLock一次
811 // Avoid slowing down fast path of normal mutex lock operation.
812 if (__predict_true(mtype == MUTEX_TYPE_BITS_NORMAL)) {
813 uint16_t shared = (old_state & MUTEX_SHARED_MASK);
//
814 if (__predict_true(NonPI::NormalMutexTryLock(mutex, shared) == 0)) {
815 return 0;
816 }
817 }
......
//没有获取到,state的1-0位非0
829 return NonPI::MutexLockWithTimeout(mutex, false, nullptr);
830}
其中pthread_mutex_internal_t有2种机器下的定义:一种是指针位是64位,还有一种是32位的,我只看32位的:
471struct pthread_mutex_internal_t {
472 _Atomic(uint16_t) state;
473 union {
474 _Atomic(uint16_t) owner_tid;
475 uint16_t pi_mutex_id;
476 };
477
478 PIMutex& ToPIMutex() {
479 return PIMutexAllocator::IdToPIMutex(pi_mutex_id);
480 }
481
482 void FreePIMutex() {
483 PIMutexAllocator::FreeId(pi_mutex_id);
484 }
485} __attribute__((aligned(4)));
可以看到pthread_mutex_internal_t 类型的变量在内存中的排放是: _Atomic(uint16_t) state + union.
//对于32位互斥锁,它包括以下字段:
435// Atomic(uint16_t) state;
436// atomic_int owner_tid; // 32位程序中的Atomic(uint16_t)
437//
438// state包含以下字段:
439//
440// bits: name description
441// 15-14 type mutex type, can be 0 (normal), 1 (recursive), 2 (errorcheck)
442// 13 shared process-shared flag
443// 12-2 counter - 1
444// 1-0 state lock state (0, 1 or 2)
445//
446// bits 15-13 are constant during the lifetime of the mutex.
// 15-13位在互斥对象的生存期内是不变的。
447//
448// owner_tid is used only in recursive and errorcheck Non-PI mutexes to hold the mutex owner thread id.
//owner_tid仅用于递归和错误检查以保持互斥锁所有者
16位原子变量state的1-0位的值,0表示未锁定,1表示有一个线程取走了锁,2表示有1+个线程在等待获取锁。接下来在lock和unlock的时候,我们关注16位原子变量state的1-0两位的变换,以及致使其变化的一些原子操作。
先看trylock:
554static inline __always_inline int NormalMutexTryLock(pthread_mutex_internal_t* mutex,
555 uint16_t shared) {
//16位unlocked的1-0为0
556 const uint16_t unlocked = shared | MUTEX_STATE_BITS_UNLOCKED;
//16位locked_uncontended的1-0为1
557 const uint16_t locked_uncontended = shared | MUTEX_STATE_BITS_LOCKED_UNCONTENDED;
558
559 uint16_t old_state = unlocked;
//比较&mutex->state和&old_state并交换locked_uncontended到&mutex->state,成功的话state字段1-0为1,示为有一个线程获取了锁。
560 if (__predict_true(atomic_compare_exchange_strong_explicit(&mutex->state, &old_state,
561 locked_uncontended, memory_order_acquire, memory_order_relaxed))) {
562 return 0;
563 }
564 return EBUSY;
565}
假定trylock失败了,可能的失败是:已经有1个线程获取了锁(1-0位为1),或者1+个线程在等待(1-0位为1).失败就走至NonPI::MutexLockWithTimeout(mutex, false, nullptr)。
701static int MutexLockWithTimeout(pthread_mutex_internal_t* mutex, bool use_realtime_clock,
702 const timespec* abs_timeout_or_null) {
703 uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
704 uint16_t mtype = (old_state & MUTEX_TYPE_MASK);
705 uint16_t shared = (old_state & MUTEX_SHARED_MASK);
706
707 // Handle common case first.
708 if ( __predict_true(mtype == MUTEX_TYPE_BITS_NORMAL) ) {
709 return NormalMutexLock(mutex, shared, use_realtime_clock, abs_timeout_or_null);
710 }
......
782}
579static inline __always_inline int NormalMutexLock(pthread_mutex_internal_t* mutex,
580 uint16_t shared,
581 bool use_realtime_clock,
582 const timespec* abs_timeout_or_null) {
583 if (__predict_true(NormalMutexTryLock(mutex, shared) == 0)) {
584 return 0;
585 }
586 int result = check_timespec(abs_timeout_or_null, true);
587 if (result != 0) {
588 return result;
589 }
590
591 ScopedTrace trace("Contending for pthread mutex");
//16位unlocked的1-0为0
593 const uint16_t unlocked = shared | MUTEX_STATE_BITS_UNLOCKED;
//16位locked_contended 的1-0为2
594 const uint16_t locked_contended = shared | MUTEX_STATE_BITS_LOCKED_CONTENDED;
......
//原子交换&mutex->state和locked_contended的值,如果&mutex->state旧值的1-0位不是0(未锁定),说明有至少一个线程获取了锁。
604 while (atomic_exchange_explicit(&mutex->state, locked_contended,
605 memory_order_acquire) != unlocked) {
//只允许一个线程获取锁,其他线程在此被内核加入了进程等待队列,等待被唤醒。
606 if (__futex_wait_ex(&mutex->state, shared, locked_contended, use_realtime_clock,
607 abs_timeout_or_null) == -ETIMEDOUT) {
608 return ETIMEDOUT;
609 }
610 }
611 return 0;
612}
看一下unlock:
832int pthread_mutex_unlock(pthread_mutex_t* mutex_interface) {
。。。。。。
841
842 pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);
843 uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
844 uint16_t mtype = (old_state & MUTEX_TYPE_MASK);
845 uint16_t shared = (old_state & MUTEX_SHARED_MASK);
846
847 // Handle common case first.
848 if (__predict_true(mtype == MUTEX_TYPE_BITS_NORMAL)) {
849 NonPI::NormalMutexUnlock(mutex, shared);
850 return 0;
851 }
。。。。。。
887 return 0;
888}
618static inline __always_inline void NormalMutexUnlock(pthread_mutex_internal_t* mutex,
619 uint16_t shared) {
620 const uint16_t unlocked = shared | MUTEX_STATE_BITS_UNLOCKED;
621 const uint16_t locked_contended = shared | MUTEX_STATE_BITS_LOCKED_CONTENDED;
。。。。。。
//原子交换&mutex->state和unlocked的值,如果&mutex->state旧值的1-0位是2(未锁定),说明有至少一个线程在等待获取锁。
628 if (atomic_exchange_explicit(&mutex->state, unlocked,
629 memory_order_release) == locked_contended) {
。。。。。。
//好,既然有等待的线程,那么我们就唤醒在&mutex->state等待的线程,可能是非公平锁,唤醒所有线程去竞争。
648 __futex_wake_ex(&mutex->state, shared, 1);
649 }
650}
//lock
void lock(pthread_mutex_internal_t* mutex) {
//trylock is successed
uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed)
const uint16_t unlocked = old_state | MUTEX_STATE_BITS_UNLOCKED;
old_state = unlocked;
if (__predict_true(atomic_compare_exchange_strong_explicit(&mutex->state, &old_state, locked_uncontended, memory_order_acquire, memory_order_relaxed))) {
return 0;
}
//trylock is failed
uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed)
const uint16_t unlocked = old_state | MUTEX_STATE_BITS_UNLOCKED;
const uint16_t locked_contended = old_state | MUTEX_STATE_BITS_LOCKED_CONTENDED;
//唤醒后的线程继续在此原子修改&mutex->state为locked_contended,先修改的线程不用再等待(unlock时修改为unlocked了)先进入临界区,后修改的返回值一直为locked_contended(!=unlocked),所以继续等待
while (atomic_exchange_explicit(&mutex->state, locked_contended, memory_order_acquire) != unlocked) {
if (__futex_wait_ex(&mutex->state, shared, locked_contended, use_realtime_clock, abs_timeout_or_null) == -ETIMEDOUT) {
return ETIMEDOUT;
}
}
}
//unlock
void unlock(pthread_mutex_internal_t* mutex) {
uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed)
const uint16_t unlocked = old_state | MUTEX_STATE_BITS_UNLOCKED;
const uint16_t locked_contended = old_state | MUTEX_STATE_BITS_LOCKED_CONTENDED;
//把&mutex->state重新置换为未锁定状态,有线程等待的话就唤醒在&mutex->state上等待的线程,唤醒后干甚就取看看lock里干了什么
if (atomic_exchange_explicit(&mutex->state, unlocked,memory_order_release) == locked_contended) {
__futex_wake_ex(&mutex->state, shared, 1);
}
}
但是我觉着把上面的atomic_compare_exchange_strong_explicit和atomic_exchange_explicit的memory_order换成memory_order_relaxed也是没有问题的。不知道此推断对不对,看到的可以讨论下。