Android 线程同步与互斥

        在Android OS中,提供了线程的同步与互斥机制,它们被封装成Mutex、Condition、Barrier三个类,其中前两个类是基于Linux线程API的封装;后一个类是基于前两个类的封装。我们现在只分析前两个类的封装,后一个在SurfaceFlinger中在做讲述。

        Mutex-----互斥类

      Mutex是互斥类,用于多线程访问同一个资源的时候,保证一次只有一个线程能访问该资源。

class Condition;

/*
 * Simple mutex class.  The implementation is system-dependent.
 *
 * The mutex must be unlocked by the thread that locked it.  They are not
 * recursive, i.e. the same thread can't lock it multiple times.
 */
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(); }
        inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
        inline ~Autolock() { mLock.unlock(); }
    private:
        Mutex& mLock;
    };

private:
    friend class 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

#ifdef _DEBUG_TRACE_MUTEX
    const char*     mName;
#endif
};

       上述为Mutex类的定义,三个构造函数,一个析构函数,三个成员函数,两个成员变量。

       关于Mutex的使用,除了初始化外,最重要的是lock和unlock函数的使用,它用于如下的环境:想要独占资源,必须先调用Mutex的lock函数,这样,这个区域就被锁住了。如果这块区域之前已经被别人锁住,lock函数则会等待,直到有人释放这块资源。这样系统保证一次只有一个线程能lok成功。当你对互斥区域的操作完毕,记得调用Mutex的unlock以释放互斥区域,这样,其他人的lock才可以成功返回。

      另外Mutex还提供了trylock函数,该函数只是尝试去锁住该互斥区域,使用者需要根据trylock的返回值来判断是否成功锁住了该区域。当返回0时说明“锁住了”互斥区域。

      对于这部分,Android为了开发的方便封装了Autolock类,可以说这就是一个“懒人类”。他对于开发者来说不必关心哪时候释放锁,或者说遗忘了调用释放锁操作unlock。Autolock充分利用类对象的生命周期,也就是类的构造函数和析构函数,我们先看Autolock的定义就会明白。

    class Autolock {
    public:
        inline Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); }
        inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
        inline ~Autolock() { mLock.unlock(); }
    private:
        Mutex& mLock;
    };

       可以看出Autolock的构造函数调用了Mutex的lock操作,析构函数调用了unlock操作,也就是在创建Autolock类实例时已经调用lock多互斥区加锁,在Autolock类实例生命周期结束时调用析构函数进而释放锁。这样方便了开发也极大的避免了对互斥区释放锁操作的遗忘。

Condition-----互斥类

        多线程同步我们引入如下的一个场景来做说明:

        线程A做初始化工作,而其他线程如线程B、C必须等到初始化工作完成后才能工作,即线程B、C在等待一个条件,当线程A完成初始化工作后,会触发这个条件,那么B、C线程就会被唤醒。

class Condition {
public:
    enum {
        PRIVATE = 0,
        SHARED = 1
    };

    Condition();
    Condition(int type);
    ~Condition();
    // Wait on the condition variable.  Lock the mutex before calling.
    status_t wait(Mutex& mutex);
    // same with relative timeout
    status_t waitRelative(Mutex& mutex, nsecs_t reltime);
    // Signal the condition variable, allowing one thread to continue.
    void signal();
    // Signal the condition variable, allowing all threads to continue.
    void broadcast();

private:
#if defined(HAVE_PTHREADS)
    pthread_cond_t mCond;
#else
    void*   mState;
#endif
};

        上述代码为Condition类的定义:

         wait为线程等待操作;

         waitRelative为线程定时等待操作;

         signal为线程唤醒操作,只能唤醒一个线程;

         broadcast为线程唤醒操作,可唤醒所有等待线程。
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值