首页 > 代码库 > pThread线程(三) 线程同步--条件变量
pThread线程(三) 线程同步--条件变量
条件变量(Condition Variables)
参考资料:http://game-lab.org/posts/posix-thread-cn/#5.1
条件变量是什么?
- 条件变量为我们提供了另一种线程间同步的方法,然而,互斥量是通过控制线程访问数据来实现同步,条件变量允许线程同步是基于实际数据的值。
- 如果没有条件变量,程序员需要让线程不断地轮询,以检查是否满足条件。由于线程处在一个不间断的忙碌状态,所以这是相当耗资源的。条件变量就是这么一个不需要轮询就可以解决这个问题的方法。
- 条件变量总是跟互斥锁(mutex lock)一起使用。
- 下面是使用条件变量的比较典型的过程:
主线程
| |
线程A
| Thread B
|
主线程
|
创建和销毁条件变量
函数:
pthread_cond_init (condition,attr)pthread_cond_destroy (condition)pthread_condattr_init (attr)pthread_condattr_destroy (attr)
用法:
- 条件变量必须声明为pthread_cond_t类型,并且在使用前必须要初始化。初始化,有两种方法:
- 静态初始化,像这样声明:pthread_con_t myconvar = PTHREAD_CON_INITIALIZER;
- 动态初始化,使用pthread_cond_init()函数。用创建条件变量的ID作为件参数传给线程,这种方法允许设置条件变量对象属性attr。
- 可设置的attr对象经常用来设置条件变量的属性,条件变量只有一种属性:process-thread,它的作用是允许条件变量被其它进程的线程看到。如果使用属性对象,必须是pthread_condattr_t类型(也可以赋值为NULL,作为默认值)。
注意,不是所有的实现都用得着process-shared属性。
- pthread_condattr_init()和pthread_condattr_destroy()函数是用来创建和销毁条件变量属性对象的。
- 当不再需要某条件变量时,可用pthread_cond_destroy()销毁。
条件变量的等待和信号发送
函数:
pthread_cond_wait (condition,mutex)pthread_cond_signal (condition)pthread_cond_broadcast (condition)
使用:
- pthread_cond_wait()阻塞调用线程,直到指定的条件变量收到信号。当互斥量被锁定时,应该调用这个函数,并且在等待时自动释放这个互斥量,在接收到信号后线程被唤醒,线程的互斥量会被自动锁定,程序员在线程中应当在此函数后解锁互斥量。
- pthread_cond_signal()函数常用来发信号给(或唤醒)正在等待条件变量的另一个线程,在互斥量被锁定后应该调用这个函数,并且为了pthread_cond_wait()函数的完成必须要解锁互斥量。
- 如果多个线程处于阻塞等待状态,那么必须要使用pthreads_cond_broadcast()函数,而不是pthread_cond_signal()。
- 在调用pthread_cond_wait()函数之前调用pthread_cond_signal()函数是个逻辑上的错误,所以,在使用这些函数时,正确的锁定和解锁与条件变量相关的互斥量是非常必要的,例如:
- 在调用pthread_cond_wait()之前锁定互斥量失败,可致使其无法阻塞;
- 在调用pthread_cond_signal()之后解锁互斥量失败,则致使与之对应的pthread_cond_wait()函数无法完成,并仍保持阻塞状态。
实例分析
1 /****************************************************************************** 2 * 描述: 3 * 应用Pthreads条件变量的实例代码,主线程创建三个线程,其中两个为“count”变量做 4 * 加法运算,第三个线程监视“count”的值。当“count”达到一个限定值,等待线程准备接收来 5 * 自于两个加法线程中一个的信号,等待 线程唤醒后更改“count”的值。程序继续运行直到加法 6 * 线程达到TCOUNT的值。最后,主程序打印出count的值。 7 ******************************************************************************/ 8 #include <pthread.h> 9 #include <stdio.h>10 #include <stdlib.h>11 12 #define NUM_THREADS 313 #define TCOUNT 5 //单线程轮询次数14 #define COUNT_LIMIT 7 //发送信号的次数15 int count = 0; //全局的累加量16 17 pthread_mutex_t count_mutex;18 pthread_cond_t count_threshold_cv;19 20 void *inc_count(void *t) {21 int i;22 long my_id = (long) t;23 24 for (i = 0; i < TCOUNT; i++) {25 pthread_mutex_lock(&count_mutex);26 count++;27 /*28 * 检查count的值,如果条件满足就发信号给等待线程29 * 注意,此处是用信号量锁定的。30 * */31 if (count < COUNT_LIMIT) {32 printf("inc_count(): thread %ld, count = %d Threshold reached. ",33 my_id, count);34 pthread_cond_signal(&count_threshold_cv);35 printf("Just sent signal.\n");36 }37 printf("inc_count(): thread %ld, count = %d, unlocking mutex\n", my_id,38 count);39 pthread_mutex_unlock(&count_mutex);40 41 /*为线程轮询互斥锁增加延时*/42 sleep(1);43 }44 pthread_exit(NULL);45 }46 47 void *watch_count(void *t) {48 long my_id = (long) t;49 printf("Starting watch_count(): thread %ld\n", my_id);50 51 /*锁定互斥量并等待信号,注意,pthread_cond_wait函数在等待时将自动以自动原子方式52 * 解锁互斥量。还有,请注意,如果等待线程运行到等待函数之前已经满足COUNT_LIMIT的53 * 条件判断,轮询会忽略掉等待函数,54 * */55 while (count < COUNT_LIMIT) {56 pthread_mutex_lock(&count_mutex);57 printf("watch_count(): thread %ld going into wait...\n", my_id);58 pthread_cond_wait(&count_threshold_cv, &count_mutex);59 printf("watch_count(): thread %ld Condition signal received.\n", my_id);60 61 printf("watch_count(): thread %ld count now = %d.\n", my_id, count);62 pthread_mutex_unlock(&count_mutex);63 }64 pthread_exit(NULL);65 }66 67 int main(int argc, char *argv[]) {68 int i;69 long t1 = 1, t2 = 2, t3 = 3;70 pthread_t threads[3];71 pthread_attr_t attr;72 73 /*初始化互斥量和条件变量对象*/74 pthread_mutex_init(&count_mutex, NULL);75 pthread_cond_init(&count_threshold_cv, NULL);76 77 /*创建线程时设为可连接状态,便于移植*/78 pthread_attr_init(&attr);79 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);80 pthread_create(&threads[0], &attr, watch_count, (void *) t1);81 pthread_create(&threads[1], &attr, inc_count, (void *) t2);82 pthread_create(&threads[2], &attr, inc_count, (void *) t3);83 84 /* 等待所有线程完成*/85 for (i = 1; i < NUM_THREADS; i++) {86 pthread_join(threads[i], NULL);87 }88 /*发送信号给监听线程*/89 pthread_cond_signal(&count_threshold_cv); 90 pthread_join(threads[0],NULL);91 printf("Main(): Waited on %d threads. Final value of count = %d. Done.\n",92 NUM_THREADS, count);93 94 /*清除并退出 */95 pthread_attr_destroy(&attr);96 pthread_mutex_destroy(&count_mutex);97 pthread_cond_destroy(&count_threshold_cv);98 pthread_exit(NULL);99 }
pThread线程(三) 线程同步--条件变量
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。