linux 条件变量与互斥锁
来源:互联网 发布:淘宝怎么图片保护 编辑:程序博客网 时间:2024/05/02 00:51
条件变量,与锁不同, 条件变量用于等待某个条件被触发
// 线程一代码 =================================================
pthread_mutex_lock(&mutex);
// 设置条件为true
... 操作
pthread_cond_signal(&cond); // 条件满足时通过线程二
pthread_mutex_unlock(&mutex);
// 线程二代码 =================================================
pthread_mutex_lock(&mutex);
while (条件为false)
pthread_cond_wait(&cond, &mutex); // 永久或超时等待线程一通知条件满足
修改该条件
... 操作
pthread_mutex_unlock(&mutex);
需要注意几点:
2) pthread_cond_wait调用必须和某一个mutex一起调用, 这个mutex是在外部进行加锁的mutex, 在调用pthread_cond_wait时, 内部的实现将首先将这个mutex解锁, 然后等待条件变量被唤醒, 如果没有被唤醒, 该线程将一直休眠, 也就是说, 该线程将一直阻塞在这个pthread_cond_wait调用中, 而当此线程被唤醒时, 将自动将这个mutex加锁.
解锁线程锁
等待条件为true
加锁线程锁.
基本编写的代码如下:
// 线程一代码 =================================================
pthread_mutex_lock(&mutex);
// 设置条件为true
... 操作
pthread_cond_signal(&cond); // 条件满足时通过线程二
pthread_mutex_unlock(&mutex);
// 线程二代码 =================================================
pthread_mutex_lock(&mutex);
while (条件为false)
pthread_cond_wait(&cond, &mutex); // 永久或超时等待线程一通知条件满足
修改该条件
... 操作
pthread_mutex_unlock(&mutex);
需要注意几点:
1) 第二段代码之所以在pthread_cond_wait外面包含一个while循环不停测试条件是否成立的原因是, 在pthread_cond_wait被唤醒的时候可能该条件已经不成立.
UNPV2对这个的描述是:
"Notice that when pthread_cond_wait returns, we always test the condition again, because spurious wakeups can occur: a wakeup when the desired condition is still not true.".
2) pthread_cond_wait调用必须和某一个mutex一起调用, 这个mutex是在外部进行加锁的mutex, 在调用pthread_cond_wait时, 内部的实现将首先将这个mutex解锁, 然后等待条件变量被唤醒, 如果没有被唤醒, 该线程将一直休眠, 也就是说, 该线程将一直阻塞在这个pthread_cond_wait调用中, 而当此线程被唤醒时, 将自动将这个mutex加锁.
man文档中对这部分的说明是:
pthread_cond_wait atomically unlocks the mutex (as per pthread_unlock_mutex) and waits for the condition variable cond to be signaled. The thread execution is suspended and does not consume any CPU time until the condition variable issignaled. The mutex must be locked by the calling thread on entrance to pthread_cond_wait. Before returning to the calling thread, pthread_cond_wait re-acquires mutex (as per pthread_lock_mutex).
解锁线程锁
等待条件为true
加锁线程锁.
请看具体的pthread_cond_wait代码实现:
/* 基于条件变量阻塞 / 在指定的时间之前阻塞 */bool32 ktx_condv_wait(McCondv *_cv, McMutex*mtx, si32 millis) {bool32 waitForever;struct timeval tv;struct timespec timeout;int status = 0;CVMCondVar *cv = (CVMCondVar*) _cv;CVMThreadID * self = ktx_thread_cur_get();CCEAssert(self != NULL);CCEAssert(cv != NULL);CCEAssert(mtx != NULL);waitForever = (millis < 0) ? TRUE : FALSE;if (waitForever == FALSE) {gettimeofday(&tv, NULL);timeout.tv_sec = tv.tv_sec + (millis / 1000LL);timeout.tv_nsec = tv.tv_usec * 1000;timeout.tv_nsec += (millis % 1000) * 1000000;if (timeout.tv_nsec >= 1000000000) {++timeout.tv_sec;timeout.tv_nsec -= 1000000000;}}/**************************************************/ktx_mutex_lock((McMutex*) &(self->lock));if (self->interrupted) {self->interrupted = FALSE;ktx_mutex_unlock((McMutex*) &self->lock);return FALSE;}self->notified = FALSE;self->isWaitBlocked = TRUE;/* add ourself to the wait queue that notify and notifyAll look at */CVMcondvarEnqueue(cv, self);ktx_mutex_unlock((McMutex*) &self->lock);/**************************************************/ktx_mutex_unlock(mtx); 这里解锁线程锁,下面立即进行等待条件为true/* notifies can happen now */pthread_mutex_lock(&self->wait_mutex);while (self->value == 0) {if (waitForever) {pthread_cond_wait(&self->wait_cv, &self->wait_mutex);} else {status = pthread_cond_timedwait(&self->wait_cv, &self->wait_mutex,&timeout);if (status == ETIMEDOUT) {break;}}}pthread_mutex_unlock(&self->wait_mutex);/* 获得lock之后才可以处理挂起操作:加锁线程锁 */ktx_mutex_lock((McMutex*) &self->lock);/* If we're supposed to be suspended, then suspend self: *///while (self->isSuspended) //{//suspendSelf();//}self->isWaitBlocked = FALSE;ktx_mutex_unlock((McMutex*) &(self->lock));/* ---------------------------------------- *//* reacquire condvar mutex */ktx_mutex_lock(mtx);/* find out why we were woken up */if (self->notified) {/* normal notify or notifyAll */CCEAssert(self->value == 1);/* removed from wait queue */CCEAssert(self->next == NULL && self->prev_p == NULL);} else {/* * We were woken up by linuxSyncInterruptWait() posting on * the semaphore, or the timed wait timed out. */CCEAssert(self->interrupted || !waitForever);CVMcondvarDequeueSelf(cv, self);/* removed from wait queue */CCEAssert(self->next == NULL && self->prev_p == NULL);}self->value = 0;if (self->interrupted) {self->interrupted = FALSE;return FALSE;}/* 等待超时返回失败 */if (waitForever == FALSE && status == ETIMEDOUT)return FALSE;return TRUE;}
- linux 条件变量与互斥锁
- linux 多线程编程 互斥锁与条件变量
- Linux多线程 互斥锁与条件变量使用
- 条件变量与互斥锁
- 互斥锁与条件变量
- 互斥锁与条件变量
- 条件变量与互斥锁
- 互斥锁与条件变量
- 互斥锁与条件变量
- 条件变量与互斥锁
- 互斥锁与条件变量
- 【Linux C 多线程编程】互斥锁与条件变量
- Linux C 多线程编程之互斥锁与条件变量
- Linux C 多线程编程 互斥锁与条件变量
- Linux C 多线程编程 互斥锁与条件变量
- 嵌入式 Linux C 多线程编程 互斥锁与条件变量
- LINUX下的条件变量与互斥锁的搭配使用
- 【Linux C 多线程编程】互斥锁与条件变量
- 学习OpenCV——配置CUDA环境
- sizeof的几个实例
- 大话设计模式笔记----6大原则
- VS2008 下的 gSOAP编程 客户端
- 旅图,去哪儿的Instagram实验
- linux 条件变量与互斥锁
- ATL 实现定制的 IE 浏览器栏、工具栏和桌面工具栏
- where和having的区别
- 常用的一些属性说明
- 如何控制IE的行为
- QRD7xxx camera调用流程
- 内核函数mmap的实现原理,机制
- Gallery3D源码分析
- maven配置 poi 3.5包 读写excel 2007 xlsx