2 condition & mutex
来源:互联网 发布:淘宝联盟导出excel 编辑:程序博客网 时间:2024/06/10 02:35
目录
1、概述
2、Mutex
3、Condition
1 概述
互斥量和条件变量在开发多线程应用中经常用到。
Linux提供了pthread_mutex_t pthread_cond_t及对应的操作使得用户可以方便的使用这两种机制(不了解的可以去百度下)。
Mutex和Condition是android代码中对pthread_mutex_t和pthread_cond_t 的封装,可以认为功能是一样的,只是调用方式上有些差别
当然Mutex和Condition具有更好的可操作性
2 Mutex
2.1 例子
这里通过一个小的例子,介绍如何利用Mutex方法进行互斥操作
//for mutex test public: Mutex mLock; int exit_flag; int read_exit; int write_exit; int mutex_test_start(); int mutex_test_stop(); static int thread_read(void *); static int thread_write(void *);
这里介绍下头文件中定义的相关的变量。exit_flag表示是否退出测试,read_exit表示读取线程成功退出标记 write_exit表示写线程成功退出标志
定义了两个线程函数thread_read thread_write,一个Mutex变量mLock,在线程代码中循环获取mLock,执行某些操作,最后退出
其中mutex_test_start和mutex_test_stop控制测试的开始和结束,下面看下实现
int dtPlayer::mutex_test_start(){ exit_flag=0; read_exit=0; write_exit=0; createThread(thread_read,this); createThread(thread_write,this); printf("--thread start ok\n"); return 0; }
启动线程,并初始化变量
int dtPlayer::mutex_test_stop(){ exit_flag=1; LOOP: if(read_exit&&write_exit) return 0; sleep(1); goto LOOP; }
判断是否都成功退出
int dtPlayer::thread_read(void *user){ dtPlayer *player=(dtPlayer *)user; while(player->exit_flag==0) { player->mLock.lock(); printf("thread read is running \n"); sleep(2); player->mLock.unlock(); sleep(1); } printf("--read thread exit ok\n"); player->read_exit=1; return 0; }
读线程,首先通过lock获取锁,获取成功后打印消息"thread read is running" 然后解锁,sleep 1s后重新去获取锁
int dtPlayer::thread_write(void * user){ dtPlayer *player=(dtPlayer *)user; while(player->exit_flag==0) { player->mLock.lock(); printf("thread write is running \n"); sleep(2); player->mLock.unlock(); sleep(1); } printf("--write thread exit ok\n"); player->write_exit=1; return 0; }
写线程与读线程类似,这里主要是为了模拟两个线程竞争同一把锁的情况,以及对Mutex的使用有个直观的认识
extern "C" int dt_mutex_test() { ALOGE("--mutex test before \n"); dtPlayer *player=new dtPlayer(); player->mutex_test_start(); sleep(20); player->mutex_test_stop(); ALOGE("--mutex test end \n"); return 0; }
最后是入口函数
2.2 Mutex类介绍
通过上面例子,可以了解Mutex的使用非常简单即如下序列:
Mutex mMux; mMux.lock(); **user ops** mMux.unlock();
下面介绍Mutex的定义等
源文件在framework/native/include/utils/Mutex.h中
主要有如下重要方法,首先是构造函数
inline Mutex::Mutex() { pthread_mutex_init(&mMutex, NULL); } inline Mutex::Mutex(const char* name) { pthread_mutex_init(&mMutex, NULL); } inline Mutex::Mutex(int type, const char* name) { if (type == SHARED) { 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); } }
这里给出了三种构造函数,之前介绍过,Mutex仅仅是对pthread_mutex_t及其操作的封装,因此构造函数是初始化的封装
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等也比较简单
inline Mutex::~Mutex() { pthread_mutex_destroy(&mMutex); }
析构函数
下面介绍Mutex中一个比较方便的扩展:
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相关的操作,其优点在于会在Autolock生命周期到期调用析构函数的时候会调用相应Mutex的unlock方法,这样用户就不用时刻惦记着unlock了
在使用的时候,是要配合一个已经存在的Mutex变量来使用,举例如下
Mutex mutex; int dtPlayer::test() { Mutex::Autilock lock(mutex); ***user ops*** return 0; }
使用非常方便。最主要的优点是不用惦记unlock
【说明】例子可从附件获得
3 Condition
3.1 例子
//for condition test public: Condition mCondition; Mutex mMuxCon; int resource_count; int inc_exit; int dec_exit; int condition_test_start(); int condition_test_stop(); static int thread_inc(void *); static int thread_dec(void *);
这里同样主体是两个线程,thread_inc thread_dec,resource_count是资源数量,当数量==0时,thread_dec会进入等待,等待thread_inc增加资源数量
看下实现
int dtPlayer::condition_test_start() { resource_count=0; inc_exit=0; dec_exit=0; createThread(thread_dec,this); createThread(thread_inc,this); printf("--thread start ok\n"); return 0; } int dtPlayer::condition_test_stop() { LOOP: if(inc_exit&&dec_exit) return 0; sleep(1); goto LOOP; return 0; }
初始化和结束实现,比较简单
int dtPlayer::thread_dec(void *user) { dtPlayer *player=(dtPlayer *)user; player->mMuxCon.lock(); while(player->resource_count==0) { printf("start wait \n"); player->mCondition.wait(player->mMuxCon); } player->resource_count--; printf("decremen resource count \n"); player->mMuxCon.unlock(); player->dec_exit=1; return 0; }
资源递减线程,首先获取互斥锁,然后判断资源数量,如果资源数量==0,则调用wait方法,wait参数是互斥锁,如果了解pthread_cond_t操作可以知道,wait会释放互斥锁
然后等待条件变量被激活,当被激活时会重新锁住,然后继续执行。也就是说这里wait会释放player->mMuxCon互斥锁
int dtPlayer::thread_inc(void *user) { dtPlayer *player=(dtPlayer *)user; player->mMuxCon.lock(); if(player->resource_count==0) { printf("increment resource count \n"); player->mCondition.signal(); } player->resource_count++; player->mMuxCon.unlock(); player->inc_exit=1; return 0; }
资源递增线程同样也是先获取锁,然后判断资源数量,如果发现count==0,则发送信号,此时可能有资源消耗线程等待,同时调用player->resource_count++; 增加资源
这里可以得出结论wait会释放锁,因为如果不释放则当数量==0时,thread_inc将无法得到锁
extern "C" int dt_condition_test() { ALOGE("--condition test before \n"); dtPlayer *player=new dtPlayer(); player->condition_test_start(); player->condition_test_stop(); ALOGE("--condition test end \n"); return 0; }
最后是测试入口
【说明】例子在附件中
3.2 Condition类介绍
下面介绍下Condition类
源文件:framework/native/include/utils/Condition.h
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
重要的方法及成员,都是围绕mCond也就是pthread_cond_t展开,看下具体实现
inline Condition::Condition() { pthread_cond_init(&mCond, NULL); } inline Condition::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); } } inline Condition::~Condition() { pthread_cond_destroy(&mCond); }
构造函数==初始化
inline status_t Condition::wait(Mutex& mutex) { return -pthread_cond_wait(&mCond, &mutex.mMutex); }
wait函数
inline void Condition::signal() { pthread_cond_signal(&mCond); } inline void Condition::broadcast() { pthread_cond_broadcast(&mCond); }
唤醒函数,signal和broadcast的区别是signal只唤醒一个线程,而boradcast将唤醒所有线程
【结束】
- 2 condition & mutex
- mutex and Condition Variables
- android mutex and condition
- boost mutex condition
- pthread condition mutex
- 线程同步:Mutex和Condition
- mutex 和 condition variable[转载]
- mutex和condition的用法
- Android同步类:Mutex和Condition
- Android同步类:Mutex和Condition
- Android同步类:Mutex和Condition
- 线程同步: mutex, semaphore, condition(ZT)[转载]
- 多线程mutex locker condition简单封装
- 什么时候mutex不够,还需要condition variable
- Android同步类:Mutex和Condition
- mutex、condition与pthread_cond_wait()函数的使用
- 什么时候mutex不够,还需要condition variable?
- Android同步类:Mutex和Condition
- PL/SQL变量
- HDU 1050——Moving Tables
- 在android 输出log 信息 用于调试
- 信号量、互斥体和自旋锁
- 数据挖掘中易犯的几大错误(转)
- 2 condition & mutex
- Mysql 修改字符编码
- C++编程思想 12章运算符重载
- C和C++相互调用
- PL/SQL判断
- Placing Lampposts------UVA10859-----DP
- 结构变量作为方法的参数调用,在方法内部使用的“坑”你遇到过吗?
- Linux 信号signal处理函数
- PL/SQL循环