条件是线程同步的另一种方法,下面是借鉴链接:
http://blog.chinaunix.net/uid-1849361-id-2825417.html
http://www.ibm.com/developerworks/cn/linux/thread/posix_thread3/index.html#icomments
基本概念和原理:
互斥对象是线程程序必需的工具,但它们并非万能的。例如,如果线程正在等待共享数据内某个条件出现,那会发生什么呢?代码可以反复对互斥对象锁定和解锁, 以检查值的任何变化。同时,还要快速将互斥对象解锁,以便其它线程能够进行任何必需的更改。这是一种非常可怕的方法,因为线程需要在合理的时间范围内频繁 地循环检测变化。
在每次检查之间,可以让调用线程短暂地进入睡眠,比如睡眠三秒钟,但是因此线程代码就无法最快作出响应。真正需要的是这样一种方法,当线程在等待满足某些 条件时使线程进入睡眠状态。一旦条件满足,还需要一种方法以唤醒因等待满足特定条件而睡眠的线程。如果能够做到这一点,线程代码将是非常高效的,并且不会 占用宝贵的互斥对象锁。这正是 POSIX 条件变量能做的事!
使用过程:
首先需要锁定互斥对象,然后线程将调用 pthread_cond_wait(&mycond,&mymutex)。pthread_cond_wait() 调用相当复杂,pthread_cond_wait() 所做的第一件事就是同时对互斥对象解锁(于是其它线程可以进行加锁),并等待条件 mycond 发生(这样当 pthread_cond_wait() 接收到另一个线程的“信号”时,它将苏醒),现在互斥对象已被解锁。此时,pthread_cond_wait() 调用还未返回,因为它要对互斥对象进行加锁。 然后执行相关的操作。
关于mycond:
等待条件 mycond 通常是一个阻塞操作,这意味着线程将睡眠,在它苏醒之前不会消耗 CPU 周期。这正是我们期待发生的情况。线程将一直睡眠,直到特定条件发生,在这期间不会发生任何浪费 CPU 时间的繁忙查询。从线程的角度来看,它只是在等待 pthread_cond_wait() 调用返回。
整个过程是这样的:
1)本线程加锁
2)调用pthread_cond_wait 解锁,然后进入cpu的睡眠。
3)其他线程加锁并且修改了条件,然后解锁
4)本线程加锁,获得条件,pthread_cond_wait返回然后运行。
5)本线程解锁,整个过程完成。
//函数目的:第一个线程需要保证count的值为整数时对count自减,所以要等待其值为整数,这是对实际情况的模拟
//注意除了加锁和解锁,所有的函数要判断返回值是否正确
//用到的新函数如下:
//pthread_cond_init()
//pthread_cond_destroy()
//pthread_cond_signal()
//pthread_cond_broadcast()
//pthread_cond_wait()
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t mymutex;
pthread_cond_t mycond;
unsigned int count = 0;
void * first_thread (void *arg)
{
pthread_mutex_lock(&mymutex);
printf("1\n");
if(pthread_cond_wait(&mycond,&mymutex) )
printf("cond wait error\n");
//这是等待条件满足后要执行的代码
count--;
printf("2\n");
pthread_mutex_unlock(&mymutex);
pthread_exit(NULL);
}
void * second_thread(void *arg)
{
pthread_mutex_lock(&mymutex);
printf("3\n");
count++;
// if(pthread_cond_signal(&mycond))
// printf("signal error\n"); //唤醒第一个正在睡眠的线程
if(pthread_cond_broadcast(&mycond))
printf("broadcast error\n"); //唤醒所有正在睡眠的线程
printf("4\n");
pthread_mutex_unlock(&mymutex);
pthread_exit(NULL);
}
int main()
{
int res; //查看返回值
int hThread1,hThread2; //创建两个线程
//初始化锁和条件
if(res = pthread_mutex_init(&mymutex,NULL) )
printf("mutex init error\n");
if( res = pthread_cond_init(&mycond,NULL) )
printf("cond init error\n");
if(res = pthread_create(&hThread1,NULL,first_thread,NULL))
printf("create thread1 error\n");
if(res = pthread_create(&hThread2,NULL,second_thread,NULL) )
printf("create thread2 error\n");
if( pthread_join(hThread1,NULL) )
printf("hThread1 join error\n");
if( pthread_join(hThread2,NULL) )
printf("hThread2 join error\n");
//两个线程结束后释放锁和条件资源
if(pthread_mutex_destroy(&mymutex))
printf("mutex_destroy error\n");
if(pthread_cond_destroy(&mycond))
printf("cond_destroy error\n");
return 0;
}