linux 条件变量
来源:互联网 发布:网站存在sql注入漏洞 编辑:程序博客网 时间:2024/05/18 16:54
1. 相关函数
#include <pthread.h>
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);
2. 说明
条件变量是一种同步机制,允许线程挂起,直到共享数据上的某些条件得到满足。条件变量上的基本操作有:触发条件(当条件变为 true 时);等待条件,挂起线程直到其他线程触发条件。
条件变量要和互斥量相联结,以避免出现条件竞争--一个线程预备等待一个条件变量,当它在真正进入等待之前,另一个线程恰好触发了该条件。
pthread_cond_init 使用 cond_attr 指定的属性初始化条件变量 cond,当 cond_attr 为 NULL 时,使用缺省的属性。LinuxThreads 实现条件变量不支持属性,因此 cond_attr 参数实际被忽略。
pthread_cond_t 类型的变量也可以用 PTHREAD_COND_INITIALIZER 常量进行静态初始化。
pthread_cond_signal 使在条件变量上等待的线程中的一个线程重新开始。如果没有等待的线程,则什么也不做。如果有多个线程在等待该条件,只有一个能重启动,但不能指定哪一个。
pthread_cond_broadcast 重启动等待该条件变量的所有线程。如果没有等待的线程,则什么也不做。
pthread_cond_wait 自动解锁互斥量(如同执行了 pthread_unlock_mutex),并等待条件变量触发。这时线程挂起,不占用 CPU 时间,直到条件变量被触发。在调用 pthread_cond_wait 之前,应用程序必须加锁互斥量。pthread_cond_wait 函数返回前,自动重新对互斥量加锁(如同执行了 pthread_lock_mutex)。
互斥量的解锁和在条件变量上挂起都是自动进行的。因此,在条件变量被触发前,如果所有的线程都要对互斥量加锁,这种机制可保证在线程加锁互斥量和进入等待条件变量期间,条件变量不被触发。
pthread_cond_timedwait 和 pthread_cond_wait 一样,自动解锁互斥量及等待条件变量,但它还限定了等待时间。如果在 abstime 指定的时间内 cond 未触发,互斥量 mutex 被重新加锁,且 pthread_cond_timedwait 返回错误 ETIMEDOUT。abstime 参数指定一个绝对时间,时间原点与 time 和 gettimeofday 相同:abstime = 0 表示 1970 年 1 月 1 日 00:00:00 GMT。
pthread_cond_destroy 销毁一个条件变量,释放它拥有的资源。进入 pthread_cond_destroy 之前,必须没有在该条件变量上等待的线程。在 LinuxThreads 的实现中,条件变量不联结资源,除检查有没有等待的线程外,pthread_cond_destroy 实际上什么也不做。
3. 取消
pthread_cond_wait 和 pthread_cond_timedwait 是取消点。如果一个线程在这些函数上挂起时被取消,线程立即继续执行,然后再次对 pthread_cond_wait 和 pthread_cond_timedwait 在 mutex 参数加锁,最后执行取消。因此,当调用清除处理程序时,可确保,mutex 是加锁的。
4. 异步信号安全(Async-signal Safety)
条件变量函数不是异步信号安全的,不应当在信号处理程序中进行调用。特别要注意,如果在信号处理程序中调用 pthread_cond_signal 或 pthread_cond_boardcast 函数,可能导致调用线程死锁。
5. 返回值
在执行成功时,所有条件变量函数都返回 0,错误时返回非零的错误代码。
6. 错误代码
pthread_cond_init, pthread_cond_signal, pthread_cond_broadcast, 和 pthread_cond_wait 从不返回错误代码。
pthread_cond_timedwait 函数出错时返回下列错误代码:
ETIMEDOUT abstime 指定的时间超时时,条件变量未触发
EINTR pthread_cond_timedwait 被触发中断
pthread_cond_destroy 函数出错时返回下列错误代码:
EBUSY 某些线程正在等待该条件变量
结果
#include <pthread.h>
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);
2. 说明
条件变量是一种同步机制,允许线程挂起,直到共享数据上的某些条件得到满足。条件变量上的基本操作有:触发条件(当条件变为 true 时);等待条件,挂起线程直到其他线程触发条件。
条件变量要和互斥量相联结,以避免出现条件竞争--一个线程预备等待一个条件变量,当它在真正进入等待之前,另一个线程恰好触发了该条件。
pthread_cond_init 使用 cond_attr 指定的属性初始化条件变量 cond,当 cond_attr 为 NULL 时,使用缺省的属性。LinuxThreads 实现条件变量不支持属性,因此 cond_attr 参数实际被忽略。
pthread_cond_t 类型的变量也可以用 PTHREAD_COND_INITIALIZER 常量进行静态初始化。
pthread_cond_signal 使在条件变量上等待的线程中的一个线程重新开始。如果没有等待的线程,则什么也不做。如果有多个线程在等待该条件,只有一个能重启动,但不能指定哪一个。
pthread_cond_broadcast 重启动等待该条件变量的所有线程。如果没有等待的线程,则什么也不做。
pthread_cond_wait 自动解锁互斥量(如同执行了 pthread_unlock_mutex),并等待条件变量触发。这时线程挂起,不占用 CPU 时间,直到条件变量被触发。在调用 pthread_cond_wait 之前,应用程序必须加锁互斥量。pthread_cond_wait 函数返回前,自动重新对互斥量加锁(如同执行了 pthread_lock_mutex)。
互斥量的解锁和在条件变量上挂起都是自动进行的。因此,在条件变量被触发前,如果所有的线程都要对互斥量加锁,这种机制可保证在线程加锁互斥量和进入等待条件变量期间,条件变量不被触发。
pthread_cond_timedwait 和 pthread_cond_wait 一样,自动解锁互斥量及等待条件变量,但它还限定了等待时间。如果在 abstime 指定的时间内 cond 未触发,互斥量 mutex 被重新加锁,且 pthread_cond_timedwait 返回错误 ETIMEDOUT。abstime 参数指定一个绝对时间,时间原点与 time 和 gettimeofday 相同:abstime = 0 表示 1970 年 1 月 1 日 00:00:00 GMT。
pthread_cond_destroy 销毁一个条件变量,释放它拥有的资源。进入 pthread_cond_destroy 之前,必须没有在该条件变量上等待的线程。在 LinuxThreads 的实现中,条件变量不联结资源,除检查有没有等待的线程外,pthread_cond_destroy 实际上什么也不做。
3. 取消
pthread_cond_wait 和 pthread_cond_timedwait 是取消点。如果一个线程在这些函数上挂起时被取消,线程立即继续执行,然后再次对 pthread_cond_wait 和 pthread_cond_timedwait 在 mutex 参数加锁,最后执行取消。因此,当调用清除处理程序时,可确保,mutex 是加锁的。
4. 异步信号安全(Async-signal Safety)
条件变量函数不是异步信号安全的,不应当在信号处理程序中进行调用。特别要注意,如果在信号处理程序中调用 pthread_cond_signal 或 pthread_cond_boardcast 函数,可能导致调用线程死锁。
5. 返回值
在执行成功时,所有条件变量函数都返回 0,错误时返回非零的错误代码。
6. 错误代码
pthread_cond_init, pthread_cond_signal, pthread_cond_broadcast, 和 pthread_cond_wait 从不返回错误代码。
pthread_cond_timedwait 函数出错时返回下列错误代码:
ETIMEDOUT abstime 指定的时间超时时,条件变量未触发
EINTR pthread_cond_timedwait 被触发中断
pthread_cond_destroy 函数出错时返回下列错误代码:
EBUSY 某些线程正在等待该条件变量
7. 举例
#include <stdlib.h> #include <stdio.h> #include <pthread.h> #include <errno.h> int x = 0; int y = 0; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond = PTHREAD_COND_INITIALIZER; static void pthread_func_1 (void); static void pthread_func_2 (void); int main (void) { pthread_t pt_1 = 0; pthread_t pt_2 = 0; int ret = 0; pthread_mutex_init (&mutex, NULL); ret = pthread_create (&pt_1, NULL, (void *)pthread_func_1, NULL); if (ret != 0) { perror ("pthread_1_create"); } ret = pthread_create (&pt_2, NULL, (void *)pthread_func_2, NULL); if (ret != 0) { perror ("pthread_2_create"); } pthread_join (pt_1, NULL); pthread_join (pt_2, NULL); printf ("x:%d, y:%d", x, y); printf ("main programme exit!\n"); return 0; } static void pthread_func_1 (void) { printf("pthread_func_1 1111111\n"); pthread_mutex_lock(&mutex); printf("pthread_func_1 22222222\n"); while (x <= y) { printf("pthread_cond_wait before\n"); pthread_cond_wait(&cond, &mutex); printf("pthread_cond_wait after\n"); } x = 2; y = 1; printf("pthread_func_1 33333333\n"); pthread_mutex_unlock(&mutex); printf("pthread_func_1 444444444\n"); pthread_exit(0);}static void pthread_func_2 (void) { printf("pthread_func_2 1111111\n"); pthread_mutex_lock(&mutex); x = 3; y = 2; printf("pthread_func_2 22222222\n"); if (x > y) { printf("pthread_cond_broadcast before\n"); pthread_cond_broadcast(&cond); printf("pthread_cond_broadcast after\n"); } printf("pthread_func_2 333333333\n"); pthread_mutex_unlock(&mutex); printf("pthread_func_2 444444444\n"); pthread_exit (0); }
结果
pthread_func_1 1111111
pthread_func_1 22222222
pthread_cond_wait before
pthread_func_2 1111111
pthread_func_2 22222222
pthread_cond_broadcast before
pthread_cond_broadcast after
pthread_func_2 333333333
pthread_func_2 444444444
pthread_cond_wait after
pthread_func_1 33333333
pthread_func_1 444444444
x:2, y:1
main programme exit!
总结:前面说了一大堆,不如看例子来的明白,从最终打印结果可以看出:
线程1:lock---判断条件---wait(解锁,挂起线程,等待条件触发)---条件触发&lock(这个是wait自动执行的,能否lock上要看其他线程是否已经unlock)---后续操作---unlock
线程2:lock----处理x/y---条件ok,触发条件----unlock
所以说,通过条件变量和mutex同时使用,可以控制两个线程的执行顺序。
- Linux 下条件变量
- linux 条件变量
- linux条件变量用法
- Linux 条件变量 pthread_cond_wait
- linux 条件变量
- linux同步-条件变量
- Linux 条件变量
- Linux 条件变量 pthread_cond_wait
- linux 多线程-条件变量
- Linux 条件变量 pthread_cond_wait
- 理解 Linux 条件变量
- linux条件变量
- linux 线程 条件变量
- 理解 Linux 条件变量
- linux 条件变量--同步
- linux条件变量若干问题
- linux条件变量
- Linux _条件变量
- ArrayList和LinkedList实现
- 【js学习笔记-008】--数字.算术运算
- notes客户端表单通过代理保存的问题
- D3学习一
- hdu 1520-树形DP
- linux 条件变量
- cygwin下安装软件
- golang template传递值的第二种方法 利用map[string]interface{}
- 项目中引入了大量的第三方架包所导致的tomcat内存溢出的解决方法(java.util.concurrent.ExecutionException: java.lang.OutOfMemoryErro
- Js 正则表达式对象(方法:exec、test、match、search)
- C# 3.0特性之Lambda表达式
- Visual States in WPF 4.0
- Java Annotation
- 剪断的翅膀,如何起飞