1)线程配合工作的例子
例子:主线程对va变量循环+1,次线程发现va==5时,打印va的值并将va清0,如果va的值!=5就什么都不做。
像这种多线程通过共享数据然后配合工作的例子很多,例子很简单,但是足以说明多线程相互配合的情况
采用最笨的实现方法:次线程循环检测va的值,然后做出相应的响应。
pth_cond.c
这种循环检测的方法虽然简单,但是存在很大的问题,那就是当va不满足时,次线程会一直在不停的循
环检测,cpu执行次线程的while时其实是在空转,白白浪费cpu的资源。
最好的方式是,当va条件不满足时就应该让次线程休眠(阻塞),等主线程将va准备好时,主动通知次线程,将它唤醒,像这样的解决方式,我们就可以使用条件变量来实现。
c++和java等线程同样有条件变量机制,条件变量的作用也是一样的,所以如果你理解c线程的条件变量,不难理解c++/java的条件变量
(2)条件变量的作用
多线程配合工作时,当线程检测到某条件不满足时就休眠,直到别的线程将条件准备好,然后通过条件变量将其唤醒。
条件变量需要在互斥锁的配合下才能工作
(3)条件变量的使用步骤
1)定义一个条件变量(全局变量)
由于条件变量需要互斥锁的配合,所以还需要定义一个线程互斥锁
2)初始化条件变量
3)使用条件变量
4)删除条件变量
也需要把互斥锁删除
(4)相关函数
1)初始化条件变量的函数
(a)函数原型
#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
· 功能
初始化条件变量,与互斥锁的初始化类似。
pthread_cond_t cond; //定义条件变量
pthread_cond_init(&cond, NULL); //第二个参数为NULL,表示不设置条件变量的属性。
也可以直接初始化:
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;//与互斥锁的初始化的原理是一样的
· 返回值:成功返回0,失败返回非零错误号
· 参数
- cond:条件变量
- attr:用于设置条件变量的属性,设置为NULL,表示使用默认属性
2)等待条件的函数
(a)函数原型
#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
· 功能:
检测条件变量cond,如果cond没有被设置,表示条件还不满足,别人还没有对cond进行设置,此时
pthread_cond_wait会休眠(阻塞),直到别的线程设置cond表示条件准备好后,才会被唤醒。
· 返回值:成功返回0,失败返回非零错误号
· 参数
- cond:条件变量
- mutex:和条件变量配合使用的互斥锁
(c)pthread_cond_wait的兄弟函数
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
多了第三个参数,用于设置阻塞时间,如果条件不满足时休眠(阻塞),但是不会一直休眠,
当时间超时后,如果cond还没有被设置,函数不再休眠
3)设置条件变量的函数
(a)函数原型
#include <pthread.h>
int pthread_cond_signal(pthread_cond_t *cond);
· 功能
当线程将某个数据准备好时,就可以调用该函数去设置cond,表示条件准备好了,
pthread_cond_wait检测到cond被设置后就不再休眠(被唤醒),线程继续运行,使用别的线程
准备好的数据来做事。
当调用pthread_cond_wait函数等待条件满足的线程只有一个时,就是用pthread_cond_signal
来唤醒,如果说有好多线程都调用pthread_cond_wait在等待时,使用
int pthread_cond_broadcast(pthread_cond_t *cond);
它可以将所有调用pthread_cond_wait而休眠的线程都唤醒
调用pthread_cond_signal去设置条件变量,相当是给pthread_cond_wait发送了一个线程间专
用的信号,通知调用pthread_cond_wait的线程,某某条件满足了,不要再睡了,赶紧做事吧。
4)删除条件变量
(a)函数原型
#include <pthread.h>
int pthread_cond_destroy(pthread_cond_t *cond);
pth_cond_up.c
1 有关多线程时的信号问题
1.1 所有的线程共享相同的信号处理方式
在之前的例子代码中,主线程将SIGINT信号的处理方式设置为了捕获,那么所有的次线程共享这一处理方式,
如果其中某个次线程改变了该信号的处理方式,那么所有的线程将共享这一改变
11.2 “信号屏蔽字”和“未决信号字”
(2)修改信号屏蔽字的函数
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
没有次线程时
此时整个进程只有一个主线程,整个进程的“信号屏蔽字”和“未决信号字”,就是主线程的“信号屏蔽字”
和“未决信号字”。
有次线程时
每个次线程都有自己独立的“信号屏蔽字”和“未决信号字”,次线程的“信号屏蔽字”和“未决信号字”是从主线程
的“信号屏蔽字”和“未决信号字”复制而来的,在复制时,
(1)次线程的“信号屏蔽字”会保留从主线程“信号屏蔽字”所复制的值。
(2)次线程的“未决信号字”会清空,也就是说不会保留所复制值。
如果次线程对某些信号有特殊的“响应需求”的话,可以自己调用如下函数,修改次线程自己的“信号屏蔽字”,
以实现将某个信号打开或者屏蔽。
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
3.多线程时是如何响应信号?
(1)进程收到信号后,进程会找到某一个没有屏蔽该信号的线程去处理在这个信号找哪一个线程,由进程说了算。
(2)如果所有的线程都屏蔽了该信号的话,信号发生时,进程会将未决信号记录到某个线程的“未决信号字”中。
同样的,找哪一个线程,由进程说了算
(3)当线程收到进程判给它的信号后,而且如果该信号的处理方式还是捕获的话
这个线程在运行时会被中断,然后去执行信号捕获函数,当信号捕获函数执行完毕后,才会
返回被中断的线程,接着执行
到此这篇条件变量定义(条件变量定义是什么)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/bcyy/16629.html