条件变量——精选推荐

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

条件变量
与互斥锁不同,条件变量是⽤来等待⽽不是⽤来上锁的。

条件变量⽤来⾃动阻塞⼀个线程,直到某特殊情况发⽣为⽌。

通常条件变量和互斥锁同时使⽤。

条件变量使我们可以睡眠等待某种条件出现。

条件变量是利⽤线程间共享的全局变量进⾏同步的⼀种机制,主要包括两个动作:⼀个线程等待"条件变量的条件成⽴"⽽挂起;另⼀个线程使"条件成⽴"(给出条件成⽴信号)。

条件的检测是在互斥锁的保护下进⾏的。

如果⼀个条件为假,⼀个线程⾃动阻塞,并释放等待状态改变的互斥锁。

如果另⼀个线程改变了条件,它发信号给关联的条件变量,唤醒⼀个或多个等待它的线程,重新获得互斥锁,重新评价条件。

如果两进程共享可读写的内存,条件变量可以被⽤来实现这两进程间的线程同步。

使⽤条件变量之前要先进⾏初始化。

可以在单个语句中⽣成和初始化⼀个条件变量如:pthread_cond_t
my_condition=PTHREAD_COND_INITIALIZER;(⽤于进程间线程的通信)。

可以利⽤函数pthread_cond_init动态初始化。

条件变量分为两部分: 条件和变量. 条件本⾝是由互斥量保护的. 线程在改变条件状态前先要锁住互斥量. 它利⽤线程间共享的全局变量进⾏同步的⼀种机制。

相关的函数如下:
1int pthread_cond_init(pthread_cond_t*cond,pthread_condattr_t*cond_attr); 2int pthread_cond_wait(pthread_cond_t*cond,pthread_mutex_t*mutex); 3int pt
hread_cond_timewait(pthread_cond_t*cond,pthread_mutex*mutex,const timespec*abstime); 4int pthread_cond_destroy(pthread_cond_t*cond); 5int pthread_
cond_signal(pthread_cond_t*cond); 6int pthread_cond_broadcast(pthread_cond_t*cond); //解除所有线程的阻塞
简要说明:
(1)初始化.init()或者pthread_cond_t cond=PTHREAD_COND_INITIALIER;属性置为NULL
(2)等待条件成⽴.pthread_wait,pthread_timewait.wait()释放锁,并阻塞等待条件变量为真
timewait()设置等待时间,仍未signal,返回ETIMEOUT(加锁保证只有⼀个线程wait)
(3)激活条件变量:pthread_cond_signal,pthread_cond_broadcast(激活所有等待线程)
(4)清除条件变量:destroy;⽆线程等待,否则返回EBUSY
详细说明
1. 初始化:
条件变量采⽤的数据类型是pthread_cond_t, 在使⽤之前必须要进⾏初始化, 这包括两种⽅式:
静态: 可以把常量PTHREAD_COND_INITIALIZER给静态分配的条件变量.
动态: pthread_cond_init函数, 是释放动态条件变量的内存空间之前, 要⽤pthread_cond_destroy对其进⾏清理.
#include <pthread.h> int pthread_cond_init(pthread_cond_t *restrict cond, pthread_condattr_t *restrict attr); int
pthread_cond_destroy(pthread_cond_t *cond); 成功则返回0, 出错则返回错误编号.
当pthread_cond_init的attr参数为NULL时, 会创建⼀个默认属性的条件变量; ⾮默认情况以后讨论.
2. 等待条件:
#include <pthread.h> int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restric mutex); int
pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict timeout); 成功则返回0, 出错则返回错误编号.
这两个函数分别是阻塞等待和超时等待.
等待条件函数等待条件变为真, 传递给pthread_cond_wait的互斥量对条件进⾏保护, 调⽤者把锁住的互斥量传递给函数. 函数把调⽤线程放到等待条件的线程列表上, 然后对互斥量解锁, 这两个操作是原⼦的. 这样便关闭了条件检查和线程进⼊休眠状态等待条件改变这两个操作之间的时间通道, 这样线程就不会错过条件的任何变化.
当pthread_cond_wait返回时, 互斥量再次被锁住.
3. 通知条件:
#include <pthread.h> int pthread_cond_signal(pthread_cond_t *cond); int pthread_cond_broadcast(pthread_cond_t *cond); 成功则返回0,出错则返回错误编号.
这两个函数⽤于通知线程条件已经满⾜. 调⽤这两个函数, 也称向线程或条件发送信号. 必须注意, ⼀定要在改变条件状态以后再给线程发送信号.
⽰例程序
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t mutex;
pthread_cond_t cond;
void *thread1(void *arg)
{
pthread_cleanup_push(pthread_mutex_unlock, &mutex);
//提供函数回调保护
while (1) {
printf("thread1 is running\n");
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
printf("thread1 applied the condition\n");
pthread_mutex_unlock(&mutex);
sleep(4);
}
pthread_cleanup_pop(0);
}
void *thread2(void *arg)
{
while (1) {
printf("thread2 is running\n");
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
printf("thread2 applied the condition\n");
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
int main()
{
pthread_t thid1, thid2;
printf("condition variable study!\n");
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_create(&thid1, NULL, (void *) thread1, NULL); pthread_create(&thid2, NULL, (void *) thread2, NULL); do {
pthread_cond_signal(&cond);
} while (1);
sleep(20);
pthread_exit(0);
return 0;
}
条件变量与互斥锁、信号量的区别
1.互斥锁必须总是由给它上锁的线程解锁,信号量的挂出即不必由执⾏过它的等待操作的同⼀进程执⾏。

⼀个线程可以等待某个给定信号灯,⽽另⼀个线程可以挂出该信号灯。

2.互斥锁要么锁住,要么被解开(⼆值状态,类型⼆值信号量)。

3.由于信号量有⼀个与之关联的状态(它的计数值),信号量挂出操作总是被记住。

然⽽当向⼀个条件变量发送信号时,如果没有线程等待在该条件变量上,那么该信号将丢失。

4.互斥锁是为了上锁⽽设计的,条件变量是为了等待⽽设计的,信号灯即可⽤于上锁,也可⽤于等待,因⽽可能导致更多的开销和更⾼的复杂性。

相关文档
最新文档