android 高版本加入了c++2.0,和2.0+的标准库的一些东西,例如:std::thread,当然低版本使用还是Thread,不过他们都封装了pthread。

我在9.0的Thread源码中发现了如下一段话:

39// DO NOT USE: please use std::thread4041class Thread : virtual public RefBase42{。。。。。。

可能是引入了c++2.0 or above的标准库的缘由,也可能是Thread.cpp/Mutex.cpp等的功能不如std::来的齐全,所以不推荐使用Thread类,推荐使用std::thread类,说法不正确的话,看到的朋友可以在评论区指出下。

std::相关

android使用的实现库是llvm的libc++库,thread是一个class,看一下构造函数:

//std::thread  in thread [no suffix] file290thread::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    else303        __throw_system_error(__ec, "thread constructor failed");304}276template 277void* __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]333int __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]30void31mutex::lock()32{33    int ec = __libcpp_mutex_lock(&__m_);//!!!34    if (ec)35        __throw_system_error(ec, "mutex lock failed");36}44void45mutex::unlock() _NOEXCEPT46{47    int ec = __libcpp_mutex_unlock(&__m_);//!!!48    (void)ec;49    _LIBCPP_ASSERT(ec == 0, "call to mutex::unlock failed");50}//mutex_destructor.cpp31class _LIBCPP_TYPE_VIS mutex32{33    __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER;//!!!3435public:36    _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY37    constexpr mutex() = default;38    mutex(const mutex&) = delete;39    mutex& operator=(const mutex&) = delete;40    ~mutex() noexcept;41};424344mutex::~mutex() _NOEXCEPT45{46    __libcpp_mutex_destroy(&__m_);//!!!47}//__threading_support [no suffix]57typedef pthread_mutex_t __libcpp_mutex_t;//!!!262int __libcpp_mutex_lock(__libcpp_mutex_t *__m)263{264  return pthread_mutex_lock(__m);//!!!265}272int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)273{274  return pthread_mutex_unlock(__m);//!!!275}277int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)278{279  return pthread_mutex_destroy(__m);//!!!280}///bionic/libc/include/pthread.h41enum {42  PTHREAD_MUTEX_NORMAL = 0,43  PTHREAD_MUTEX_RECURSIVE = 1,44  PTHREAD_MUTEX_ERRORCHECK = 2,4546  PTHREAD_MUTEX_ERRORCHECK_NP = PTHREAD_MUTEX_ERRORCHECK,47  PTHREAD_MUTEX_RECURSIVE_NP  = PTHREAD_MUTEX_RECURSIVE,4849  PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL50};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承担起来。

其他的互斥体也是如此,不一一罗列。

 Thread相关

 /system/core/libutils/Threads.cpp

使用Thread,sp t = new Thread(false); t.run("threadname",PRIORITY_NORMAL);最终会调用到pthread的pthread_create方法。

/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库,实现了这套标准。看来制定标准的都在想着要做老大。

pthread lock and unlock

锁类型有三种:1.MUTEX_TYPE_BITS_NORMAL普通锁,非其余两种,2.MUTEX_TYPE_BITS_RECURSIVE支持重入,3. MUTEX_TYPE_BITS_ERRORCHECK,支持错误检查。我们只看普通锁。

798int pthread_mutex_lock(pthread_mutex_t* mutex_interface) {......807808    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位非0829    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    };477478    PIMutex& ToPIMutex() {479        return PIMutexAllocator::IdToPIMutex(pi_mutex_id);480    }481482    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     description441//   15-14     type     mutex type, can be 0 (normal), 1 (recursive), 2 (errorcheck)442//   13        shared   process-shared flag443//   12-2      counter   - 1444//   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为0556    const uint16_t unlocked           = shared | MUTEX_STATE_BITS_UNLOCKED;//16位locked_uncontended的1-0为1557    const uint16_t locked_uncontended = shared | MUTEX_STATE_BITS_LOCKED_UNCONTENDED;558559    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);706707    // 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    }590591    ScopedTrace trace("Contending for pthread mutex");//16位unlocked的1-0为0593    const uint16_t unlocked           = shared | MUTEX_STATE_BITS_UNLOCKED;//16位locked_contended 的1-0为2594    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) {。。。。。。841842    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);846847    // 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和unlock:

//lockvoid 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;        }    }}//unlockvoid 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也是没有问题的。不知道此推断对不对,看到的可以讨论下。

更多相关文章

  1. SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
  2. Android(安卓)为apk文件签名,增加修改系统时间等权限
  3. Android(安卓)EventBus的使用
  4. 百度地图开发 android App 数字签名(SHA1)获取办法
  5. 简单基站定位程序
  6. 谈谈Binder
  7. Android(安卓)thumbnail 缩略图的获取及与原始图片的映射关系
  8. TextView通过获得dimens.xml中定义的大小来动态设置字体大小
  9. Android:GPS定位 Location == null

随机推荐

  1. 关于android的广播机制里面的网络状态监
  2. Android重要控件概览(中)
  3. Android进程间通信--消息机制及IPC机制实
  4. 转:android在文本TextView中添加超链接
  5. android 横竖屏判断
  6. android 控件学习笔记 --------ViewPager
  7. Android编译过程详解(一)
  8. android监听来电去电广播
  9. Android(安卓)Media Scanner Mechanism A
  10. Android(安卓)四种定时器的写法