android底层库libutils之Mutex,Autolock研究

1)认识Mutex,Autolock

Mutex其实是对linux 线程互斥锁做了一层封装,由下面的类定义中可以发现pthread_mutex_t mMutex,这一点充分说明这一点。而在Mutex之上又做了一层封装,就出现了自动锁。自动锁在面向对象编程时,更能有效的释放锁,防止程序猿忘了释放锁,导致花时间调试。

class Mutex {
public:
    enum {
        PRIVATE = 0,
        SHARED = 1
    };
    
                Mutex();
                Mutex(const char* name);
                Mutex(int type, const char* name = NULL);
                ~Mutex();

    // lock or unlock the mutex
    status_t    lock();
    void        unlock();

    // lock if possible; returns 0 on success, error otherwise
    status_t    tryLock();

    // Manages the mutex automatically. It'll be locked when Autolock is
    // constructed and released when Autolock goes out of scope.
    class Autolock {
    public:
        inline Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); } //自动锁就是就是在构造函数中调用lock,析构函数中调用unlock,没什么大不了的。
        inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
        inline ~Autolock() { mLock.unlock(); }
    private:
        Mutex& mLock;
    };

private:
    friend class Condition; //友元是Condition,
    
    // A mutex cannot be copied
                Mutex(const Mutex&);
    Mutex&      operator = (const Mutex&);
    
#if defined(HAVE_PTHREADS)
    pthread_mutex_t mMutex;
#else
    void    _init();
    void*   mState;
#endif
};
上面可以看到Mutex类中定义的方法和linux 标注API基本保持一致,例如我们来看看Mutex构造函数,确实只是在外面又套了一层。^_^

inline Mutex::Mutex() {
    pthread_mutex_init(&mMutex, NULL);
}
inline Mutex::Mutex(__attribute__((unused)) const char* name) {
    pthread_mutex_init(&mMutex, NULL);
}
我们重点关注的是LOCK和UNLOCK过程

inline status_t Mutex::lock() {
    return -pthread_mutex_lock(&mMutex);
}
inline void Mutex::unlock() {
    pthread_mutex_unlock(&mMutex);
}
inline status_t Mutex::tryLock() {
    return -pthread_mutex_trylock(&mMutex);
}
当众多线程竞争同一个资源时,只有拿到锁的线程才有资格访问资源。其它线程只能排队等,一个一个的访问。LOCK和UNLOCK的过程一定要成对出现。既然是对linux标准api的封装,linux互斥锁的介绍我们可以参考 博文,里面介绍的很详细。

2)mutex实例

针对博文里面的例子,我把android源码中的Mutex类拿出来了,可以在地址中下载到源码。

#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>

#define status_t int    //这里由于在mutex类中有status_t类型,所以这里就加了个宏定义。
#define HAVE_PTHREADS 1
#include "Mutex.h"

pid_t gettid()
{
    return syscall(SYS_gettid);
}

Mutex s_mutex;
void *print_msg(void *arg){                                                                                                                                                             
    int i=0;  
    s_mutex.lock();
    for(i=0;i<5;i++){  
        printf("Thread:%d->output : %d\n",gettid(),i);  
        sleep(1);  
     }  
    s_mutex.unlock();
}  

int main(int argc,char** argv){  
    pthread_t id1;  
    pthread_t id2;  
    pthread_create(&id1,NULL,print_msg,NULL);  
    pthread_create(&id2,NULL,print_msg,NULL);  
    pthread_join(id1,NULL);  
    pthread_join(id2,NULL);  
    return 1;  
}  
打印log1(有锁保护的):打印结果看,只要线程拿到了这个资源的锁,就对当前资源独有控制权,其它线程不能访问该资源了。log中看,当前线程打印的结果是连续的

public@SH-NB-0022:/shared/test$ g++ mutex.cpp -o thread -lpthread //编译命令
public@SH-NB-0022:/shared/test$ ./thread 
Thread:2393->output : 0
Thread:2393->output : 1
Thread:2393->output : 2
Thread:2393->output : 3
Thread:2393->output : 4
Thread:2394->output : 0
Thread:2394->output : 1
Thread:2394->output : 2
Thread:2394->output : 3
Thread:2394->output : 4

打印log2(无锁保护的):将s_mutex.logck(),s_mutex.unlock()去掉的话,就会出现两个线程能同时访问共享资源的情况。这样是很危险的。在没有锁保护的情况下,线程1,线程2共享资源,线程1前一时刻拿到的数据,后一秒就会被线程2修改,导致异常的发生。所以在进行共享资源访问的时候,一定要加锁保护,防止意外事故发生。

public@SH-NB-0022:/shared/test$ g++ mutex.cpp -o thread -lpthread //编译命令
public@SH-NB-0022:/shared/test$ ./thread 
Thread:2760->output : 0
Thread:2761->output : 0
Thread:2760->output : 1
Thread:2761->output : 1
Thread:2761->output : 2
Thread:2760->output : 2
Thread:2761->output : 3
Thread:2760->output : 3
Thread:2761->output : 4
Thread:2760->output : 4

3)autolock实例

自动锁更加简单,只需要在访问共享资源入口出加一个自动锁就行了,如下代码所示。打印结果和上面的log1是一样的。

Mutex s_mutex;
void *print_msg(void *arg){
    int i=0;
    Mutex::Autolock autoLock(s_mutex);
    for(i=0;i<5;i++){
        printf("Thread:%d->output : %d\n",gettid(),i);
        sleep(1);
     }
}

总结:Mutex还是相当简单的,用好了Mutex会让程序更安全稳定。如果单纯只是使用的话,你可以不去研究android mutex类(其实也没多少东西),会用就行了。我一般都习惯性的把类拿出来,在PC机上验证一下。总之就是在互斥资源的入口和出口分别加上lock()和unlock(),就行了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值