名称
pthread_cond_init, pthread_cond_destroy, pthread_cond_signal,
pthread_cond_broadcast, pthread_cond_wait, pthread_cond_timedwait - 状态操作。
大纲
#include
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct
timespec *abstime);
int pthread_cond_destroy(pthread_cond_t *cond);
描述
状态变量是一种同步设备,它允许线程挂起并放弃CPU时间以等待某些共享变量满足状态。操作状态变量的基本操作:当状态满足时发送信号,等待状态满足,在其它线程发送状态信号之前挂起线程。
状态变量通常和互斥体联系在一起,为了避免竞争状态出现,一个线程准备等待一个状态变量之前另外一个线程要先设置好状态信号。
pthread_cond_init初始化状态变量cond,使用cond_attr中定义了的状态属性,如果cond_attr为NULL,将会使用默认属性。LinuxThreads的实现支持没有任何属性的cond_attr,因此,cond_attr就是被忽略的。
pthread_cond_t类型的变量也可以使用PTHREAD_COND_INITIALIZER.常量进行静态的初始化。
pthread_cond_signal函数重新开始一个正在等待cond变量的线程。如果没有线程在等待cond变量,不执行任何操作。如果有多个线程都在等待,某个匹配的线程会被重新开始,但是不一定是哪个。
pthread_cond_broadcast函数重新开始所有在等待cond变量的线程。如果没有线程在等待cond变量,不执行任何操作。
pthread_cond_wait函数对互斥体进行原子的解锁工作(就像pthread_unlock_mutex),然后等待状态信号。线程被挂起并不消耗CPU时间,直到发送状态信号。互斥体必须被调用者锁定。在返回调用线程之前,互斥锁被pthread_cond_wait拥有。
释放互斥体和在状态变量上挂起是自动进行的。因此,如果所有的线程经常在状态信号之前要求互斥体,这会保证在线程在状态变量上锁定互斥体的期间状态变量不会触发信号。
pthread_cond_timedwait函数自动释放互斥体并且等待cond状态,就像pthread_cond_wait所做的一样,但是它限制了最大的等待时间。如果cond没有在一定时间内用abstime中没有指定的时间做标记,互斥体会重新获得,然后返回错误码ETIMEOUT。 abstime参数指定绝对时间,和time(2)和gettimeofday(2)的一样:以格林威治时间1970年1月1日零点为起点。
pthread_cond_destroy函数销毁状态变量,释放它可能持有的资源。没有线程必须在这里等待状态变量。在LinuxThreads实现中,状态变量不与任何资源有关系,所以这个接口除了检查状态变量上是否有等待的线程之外不做任何事。
取消
pthread_cond_wait和pthread_cond_timedwait都是取消点。如果某个线程在某个这样的函数中挂起后又被取消,该线程会重新开始执行,然后再锁定互斥体。(尚未完成!)
同步信号安全
状态函数不是同步安全的,不应该出现在信号处理函数中。特别的,从信号处理函数中调用pthread_cond_signal或pthread_cond_broadcast会导致死锁。
返回值
所有状态变量函数在成功的时候返回0,在出错的时候返回出错码。
错误码
pthread_cond_init, pthread_cond_signal, pthread_cond_broadcast和pthread_cond_wait从来都不会返回出错码。
pthread_cond_timedwait函数在出错时返回下面的出错码:
ETIMEOUT:状态变量在abstime限定时间内没有激发信号。
EINTR:pthread_cond_timedwait被信号中断。
pthread_cond_destroy函数在出错时返回下面的出错码:
EBUSY:有线程正在cond上等待。
作者
Xavier Leroy
参见
pthread_condattr_init(3), pthread_mutex_lock(3), pthread_mutex_unlock(3)
gettimeofday(2), nanosleep(2).
示例
考虑两个共享变量x和y,使用互斥体mut进行保护,一个状态变量cond在x大于y时激发信号。
int x,y;
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
一直等待,直到x大于y:
pthread_mutex_lock(&mut);
while (x <= y) {
pthread_cond_wait(&cond, &mut);
}
/* operate on x and y */
pthread_mutex_unlock(&mut);
修改x和y可能会使x大于y。如果需要就应该发送信号:
pthread_mutex_lock(&mut);
/* modify x and y */
if (x > y) pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mut);
如果可以证明,至多有一个等待中的线程需要醒来(例如,只有两个线程,通过x和y联系起来),pthread_cond_signal可以作为可选的更有效率的轻量级的pthread_cond_broadcast.。如果不能确定,使用pthread_cond_broadcast函数。
要在5秒钟内等待x大于y,像下面:
struct timeval now;
struct timespec timeout;
int retcode;
pthread_mutex_lock(&mut);
gettimeofday(&now);
timeout.tv_sec = now.tv_sec + 5;
timeout.tv_nsec = now.tv_usec * 1000;
retcode = 0;
while (x <= y && retcode != ETIMEDOUT) {
retcode = pthread_cond_timedwait(&cond, &mut, &timeout);
}
if (retcode == ETIMEDOUT) {
/* timeout occurred */
} else {
/* operate on x and y */
}
pthread_mutex_unlock(&mut);
条件锁pthread_cond_t 的应用
最新推荐文章于 2022-07-30 22:09:11 发布