加入收藏 | 设为首页 | 会员中心 | 我要投稿 济南站长网 (https://www.0531zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Unix > 正文

UNIX环境高级编程:线程同步之条件变量及属性

发布时间:2016-08-01 18:23:01 所属栏目:Unix 来源:站长网
导读:条件变量变量也是出自POSIX线程标准,另一种线程同步机制。主要用来等待某个条件的发生。可以用来同步同一进程中的各个线程。当然如果一个条件变量存放在多个进
副标题[/!--empirenews.page--]

条件变量变量也是出自POSIX线程标准,另一种线程同步机制。主要用来等待某个条件的发生。可以用来同步同一进程中的各个线程。当然如果一个条件变量存放在多个进程共享的某个内存区中,那么还可以通过条件变量来进行进程间的同步。

每个条件变量总是和一个互斥量相关联,条件本身是由互斥量保护的,线程在改变条件状态之间必须要锁住互斥量。条件变量相对于互斥量最大的优点在于允许线程以无竞争的方式等待条件的发生。当一个线程获得互斥锁后,发现自己需要等待某个条件变为真,如果是这样,该线程就可以等待在某个条件上,这样就不需要通过轮询的方式来判断添加,大大节省了CPU时间。

在互斥量一文中说过:互斥量是用于上锁,而不是用于等待;现在这句话可以加强为:互斥量是用于上锁,条件变量用于等待;

条件变量声明为pthread_cond_t数据类型,在<bits/pthreadtypes.h>中有具体的定义。

1条件变量初始化和销毁

#include <pthread.h>  
int pthread_cond_init (pthread_cond_t *cond,const pthread_condattr_t *cond_attr) ;  
int pthread_cond_destroy (pthread_cond_t *cond);  
                                        两者的返回值都是:若成功则返回0,否则返回错误号

上面两个函数分别由于条件变量的初始化和销毁。

和互斥量的初始化一样,如果条件变量是静态分配的,可以通过常量进行初始化,如下:

pthread_cond_t mlock = PTHREAD_COND_INITIALIZER;  

也可以通过pthread_cond_init()进行初始化,对于动态分配的条件变量由于不能直接赋值进行初始化,就只能采用这种方式进行初始化。那么当不在需要使用条件变量,释放底层空间之前,需要调用pthread_cond_destroy()销毁该条件所占用的资源。

2条件变量的使用

/*  等待条件变为真 */
 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_signal (pthread_cond_t *cond);  
      
 /* 唤醒等待该条件的所有线程 */
 int pthread_cond_broadcast (pthread_cond_t *cond);

(1)pthread_cond_wait()函数用于等待条件被触发。该函数传入两个参数,一个条件变量一个互斥量,函数将条件变量和互斥量进行关联,互斥量对该条件进行保护,传入的互斥量必须是已经锁住的。调用pthread_cond_wait()函数后,会原子的执行以下两个动作:

将调用线程放到等待条件的线程列表上,即进入睡眠;

对互斥量进行解锁;

由于这两个操作时原子操作,这样就关闭了条件检查和线程进入睡眠等待条件改变这两个操作之间的时间通道,这样就不会错过任何条件的变化。

当pthread_cond_wait()返回后,互斥量会再次被锁住。

(2)pthread_cond_timedwait()函数和pthread_cond_wait()的工作方式相似,只是多了一个等待时间。等待时间的结构为struct timespec:

struct timespec{  
time_t  tv_sec    //Seconds.  
long    tv_nsec   //Nanoseconds.  
};

函数要求传入的时间值是一个绝对值,不是相对值,例如,想要等待3分钟,必须先获得当前时间,然后加上3分钟。

要想获得当前系统时间的timespec值,没有直接可调用的函数,需要通过调用gettimeofday函数获取timeval结构,然后转换成timespec结构,转换公式就是:

timeSpec.tv_sec = timeVal.tv_sec;  
timeSpec.tv_nsec = timeVal.tv_usec * 1000;

所以要等待3分钟,timespec时间结构的获得应该如下所示:

struct timeval now;  
struct timespec until;  
gettimeofday(&now);//获得系统当前时间  
      
//把时间从timeval结构转换成timespec结构  
until.tv_sec = now.tv_sec;  
until.tv_nsec = now.tv_usec * 1000;  
      
//增加min  
until.tv_sec += 3 * 60;

(编辑:济南站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读