Android中同步类Mutex(AutoMutex)与Condition。

pthread_mutexattr_t attr;

pthread_mutexattr_init(&attr);

pthread_mutexattr_setpshared(&attr,PTHREAD_PROCESS_SHARED);

pthread_mutex_init(&mMutex,&attr);

pthread_mutexattr_destroy(&attr);

} else {

pthread_mutex_init(&mMutex, NULL);

}

}

inlineMutex::~Mutex() {

pthread_mutex_destroy(&mMutex);

}

inlinestatus_t Mutex::lock() {

return -pthread_mutex_lock(&mMutex);

}

inline voidMutex::unlock() {

pthread_mutex_unlock(&mMutex);

}

inlinestatus_t Mutex::tryLock() {

return -pthread_mutex_trylock(&mMutex);

}

#endif //HAVE_PTHREADS

//---------------------------------------------------------------------------

/*

* Automatic mutex.  Declare one of these at the top of afunction.

* When the function returns, it will go out ofscope, and release the

* mutex.

*/

typedefMutex::Autolock AutoMutex;

//---------------------------------------------------------------------------

}; //namespace android

// ---------------------------------------------------------------------------

#endif //_LIBS_UTILS_MUTEX_H

1.2  Condition代码分析

Condition条件类,在多线程同步中,主要是下面这种使用场景使用到condition。

线程A做初始化工作,而其他线程,比如线程B、C必须等到A初始化工作完后才能工作,即线程B、C在等待一个条件,我们称B、C为等待者。

当线程A完成初始化工作时,会触发这个条件,那么等待者B、C就会被唤醒。触发这个条件的A就是触发者。

上面的使用场景非常形象,而且条件类提供的函数也非常形象,它的代码如下所示:

system/core/include/utils/Condition.h

/*

* Copyright © 2007 The Android Open SourceProject

*

* Licensed under the Apache License, Version2.0 (the “License”);

* you may not use this file except incompliance with the License.

* You may obtain a copy of the License at

*

*     http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreedto in writing, software

* distributed under the License is distributedon an “AS IS” BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANYKIND, either express or implied.

* See the License for the specific languagegoverning permissions and

* limitations under the License.

*/

#ifndef_LIBS_UTILS_CONDITION_H

#define_LIBS_UTILS_CONDITION_H

#include<stdint.h>

#include<sys/types.h>

#include<time.h>

#if defined(HAVE_PTHREADS)

# include<pthread.h>

#endif

#include<utils/Errors.h>

#include<utils/Mutex.h>

#include<utils/Timers.h>

//---------------------------------------------------------------------------

namespace android {

//---------------------------------------------------------------------------

/*

* Condition variable class.  The implementation is system-dependent.

*

* Condition variables are paired up withmutexes.  Lock the mutex,

* call wait(), then either re-wait() if thingsaren’t quite what you want,

* or unlock the mutex and continue.  All threads calling wait() must

* use the same mutex for a given Condition.

*/

class Condition {

public:

enum {

PRIVATE = 0,

SHARED = 1

};

//两种类型:PRIVATE是进程内部使用的;SHARED是适用于跨进程共享的。

//如不指定,缺省是PRIVATE的类型。

enum WakeUpType {

WAKE_UP_ONE = 0,

WAKE_UP_ALL = 1

};

Condition(); 构造函数

Condition(int type);//构造函数,type就是上面的那两种类型

~Condition();//析构

// Wait on the condition variable.  Lock the mutex before calling.

//线程B和C等待事件,wait这个名字也很形象

status_t wait(Mutex& mutex);

// same with relative timeout

//线程B和C的超时等待,B和C可以指定等待时间,当超过这个时间,条件却还不满足,则退出等待。

status_t waitRelative(Mutex& mutex,nsecs_t reltime);

// Signal the condition variable, allowingexactly one thread to continue.

//触发者A用来通知条件已经满足,但是B和C只有一个会被唤醒

void signal();

// Signal the condition variable, allowingone or all threads to continue.

void signal(WakeUpType type) {

if (type == WAKE_UP_ONE) {

signal();

} else {

broadcast();

}

}

// Signal the condition variable, allowingall threads to continue.

//触发者A用来通知条件已经满足,所有等待者都会被唤醒。

void broadcast();

private:

#ifdefined(HAVE_PTHREADS)

pthread_cond_t mCond;

#else

void*  mState;

#endif

};

//---------------------------------------------------------------------------

#ifdefined(HAVE_PTHREADS)

inlineCondition::Condition() {

pthread_cond_init(&mCond, NULL);

}

inlineCondition::Condition(int type) {

if(type == SHARED) {

pthread_condattr_t attr;

pthread_condattr_init(&attr);

pthread_condattr_setpshared(&attr,PTHREAD_PROCESS_SHARED);

pthread_cond_init(&mCond,&attr);

pthread_condattr_destroy(&attr);

} else {

pthread_cond_init(&mCond, NULL);

}

}

inlineCondition::~Condition() {

pthread_cond_destroy(&mCond);

}

inline status_tCondition::wait(Mutex& mutex) {

return -pthread_cond_wait(&mCond,&mutex.mMutex);

}

inline status_tCondition::waitRelative(Mutex& mutex, nsecs_t reltime) {

#ifdefined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)

struct timespec ts;

ts.tv_sec = reltime/1000000000;

ts.tv_nsec = reltime%1000000000;

return-pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);

#else //HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE

struct timespec ts;

#ifdefined(HAVE_POSIX_CLOCKS)

clock_gettime(CLOCK_REALTIME, &ts);

#else //HAVE_POSIX_CLOCKS

// we don’t support the clocks here.

struct timeval t;

gettimeofday(&t, NULL);

ts.tv_sec = t.tv_sec;

ts.tv_nsec= t.tv_usec*1000;

#endif //HAVE_POSIX_CLOCKS

ts.tv_sec += reltime/1000000000;

ts.tv_nsec+= reltime%1000000000;

if (ts.tv_nsec >= 1000000000) {

ts.tv_nsec -= 1000000000;

ts.tv_sec  += 1;

}

return -pthread_cond_timedwait(&mCond,&mutex.mMutex, &ts);

#endif //HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE

}

//inline函数

//signal()和broadcast()的实现是凭借调用了Raw API的pthread_cond_signal(&mCond)与pthread_cond_broadcast(&mCond)

//这里要重点说明的是,Condition类必须配合Mutex来使用。

// 在上面的代码中,不论是wait、waitRelative、signal还是broadcast的调用,都放在一个Mutex的lock和unlock范围中,尤其是wait和waitRelative函数的调用,这是强制性的。

inline voidCondition::signal() {

/*

* POSIX says pthread_cond_signal wakes up"one or more" waiting threads.

*However bionic follows the glibc guarantee which wakes up “exactlyone”

* waiting thread.

*

* man 3 pthread_cond_signal

*  pthread_cond_signal restarts one of the threads that are waiting on

*  the condition variable cond. If no threads are waiting on cond,

*  nothing happens. If several threads are waiting on cond, exactly one

*  is restarted, but it is not specified which.

*/

pthread_cond_signal(&mCond);

}

inline voidCondition::broadcast() {

pthread_cond_broadcast(&mCond);

}

#endif //HAVE_PTHREADS

//---------------------------------------------------------------------------

}; // namespaceandroid

//---------------------------------------------------------------------------

#endif // _LIBS_UTILS_CONDITON_H

二、为什么android要封装AutoMutex

在android系统中,死锁是非常严重的,基本都是会引起系统死机,crash,重启的,并且死锁在android系统开发中,也是会经常碰见的。所以我们要尽量避免死锁,android就给我们封装了AutoMutex。它充分利用了c++的构造与析构机制,在构造函数中 mLock.lock() 加锁,在析构函数中 mLock.unlock() 解锁。

对一个需要加锁的函数来说,我们只需要在函数开始处,AutoMutex _l(mLock)就完成了加锁,等函数退出时,这样一个临时变量就会析构,就会解锁。

三、Autolock/AutoMutex与Condition的使用

    1. Autolock/AutoMutex的使用

用法比较简单,定义一个局部临时的AutoMutex变量,在该变量定义的地方,构造函数被自动调用,会执行Mutex的lock()操作;在该变量作用域结束的地方,析构函数会被自动调用,会执行Mutex的unlock操作。

所以,你只需要在Mutex保护的区域开始的地方定义一个AutoMutex变量即可,即可实现用Mutex对该区域的保护。

  1. Condition的使用

我们看一个android原生的类是怎么使用condition和Mutex的。

这个例子是Thread类的requestExitAndWait,目的是等待工作线程退出,代码如下所示:

system/core/libutils/Threads.cpp

status_t Thread::requestExitAndWait()

{

Mutex::Autolock _l(mLock);

if (mThread == getThreadId()) {

ALOGW(

"Thread (this=%p): don’t callwaitForExit() from this "

“Thread object’s thread. It’s aguaranteed deadlock!”,

this);

return WOULD_BLOCK;

}

mExitPending = true;

while (mRunning == true) {

mThreadExitedCondition.wait(mLock);//这里wait

}

// This next line is probably not neededany more, but is being left for

// historical reference. Note that eachinterested party will clear flag.

mExitPending = false;

return mStatus;

}

那么,什么时候会触发这个条件呢?是在工作线程退出前。其代码如下所示:

int Thread::_threadLoop(void* user)

{

Thread* const self =static_cast<Thread*>(user);

spstrong(self->mHoldSelf);

wp weak(strong);

self->mHoldSelf.clear();

#ifdef HAVE_ANDROID_OS

// this is very useful for debugging withgdb

self->mTid = gettid();

#endif

bool first = true;

do {

bool result;

if (first) {

first = false;

self->mStatus =self->readyToRun();

result = (self->mStatus ==NO_ERROR);

if (result &&!self->exitPending()) {

// Binder threads (and maybeothers) rely on threadLoop

// running at least once aftera successful ::readyToRun()

// (unless, of course, thethread has already been asked to exit

// at that point).

// This is because threads areessentially used like this:

//   (new ThreadSubclass())->run();

// The caller therefore doesnot retain a strong reference to

// the thread and the thread wouldsimply disappear after the

// successful ::readyToRun()call instead of entering the

// threadLoop at least once.

result = self->threadLoop();

}

} else {

result = self->threadLoop();

}

// establish a scope for mLock

{

Mutex::Autolock _l(self->mLock);

if (result == false ||self->mExitPending) {

self->mExitPending = true;

self->mRunning = false;

// clear thread ID so thatrequestExitAndWait() does not exit if

// called by a new thread using thesame thread ID as this one.

self->mThread = thread_id_t(-1);

// note that interested observersblocked in requestExitAndWait are

// awoken by broadcast, but blockedon mLock until break exits scope

self->mThreadExitedCondition.broadcast();  //这里broadcast

break;

}

}

// Release our strong reference, to leta chance to the thread

// to die a peaceful death.

strong.clear();

// And immediately, re-acquire a strongreference for the next loop

strong = weak.promote();

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值