linux 线程学习之条件变量

http://blog.csdn.net/hemmanhui/article/details/4417433

互斥锁:用来上锁。

条件变量:用来等待,当条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。通常条件变量和互斥锁同时使用。

 

函数介绍:

 

1.

名称:

pthread_cond_init

目标:

条件变量初始化

头文件:

#include < pthread.h>

函数原形:

int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);

参数:

cptr  条件变量

attr  条件变量属性

返回值:

成功返回0,出错返回错误编号。

     

 

 

 

 

 

 

 

 

  pthread_cond_init函数可以用来初始化一个条件变量。他使用变量attr所指定的属性来初始化一个条件变量,如果参数attr为空,那么它将使用缺省的属性来设置所指定的条件变量。

 

2.

名称:

pthread_cond_destroy

目标:

条件变量摧毁

头文件:

#include < pthread.h>

函数原形:

int pthread_cond_destroy(pthread_cond_t *cond);

参数:

cptr  条件变量

返回值:

成功返回0,出错返回错误编号。

      

 

 

 

 

 

 

 pthread_cond_destroy函数可以用来摧毁所指定的条件变量,同时将会释放所给它分配的资源。调用该函数的进程也并不要求等待在参数所指定的条件变量上。

 

3.

名称:

pthread_cond_wait/pthread_cond_timedwait

目标:

条件变量等待

头文件:

#include < pthread.h>

函数原形:

int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);

int pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t mytex,const struct timespec *abstime);

参数:

cond 条件变量

mutex 互斥锁

返回值:

成功返回0,出错返回错误编号。

      

 

 

 

 

 

 

 

 

 

 第一个参数*cond是指向一个条件变量的指针。第二个参数*mutex则是对相关的互斥锁的指针。函数pthread_cond_timedwait函数类型与函数pthread_cond_wait,区别在于,如果达到或是超过所引用的参数*abstime,它将结束并返回错误ETIME.pthread_cond_timedwait函数的参数*abstime指向一个timespec结构。该结构如下:

typedef struct timespec{

       time_t tv_sec;

       long tv_nsex;

}timespec_t;

 

3.

名称:

pthread_cond_signal/pthread_cond_broadcast

目标:

条件变量通知

头文件:

#include < pthread.h>

函数原形:

int pthread_cond_signal(pthread_cond_t *cond);

int pthread_cond_broadcast(pthread_cond_t *cond);

参数:

cond 条件变量

返回值:

成功返回0,出错返回错误编号。

      

 

 

 

 

 

 

 

 参数*cond是对类型为pthread_cond_t 的一个条件变量的指针。当调用pthread_cond_signal时一个在相同条件变量上阻塞的线程将被解锁。如果同时有多个线程阻塞,则由调度策略确定接收通知的线程。如果调用pthread_cond_broadcast,则将通知阻塞在这个条件变量上的所有线程。一旦被唤醒,线程仍然会要求互斥锁。如果当前没有线程等待通知,则上面两种调用实际上成为一个空操作。如果参数*cond指向非法地址,则返回值EINVAL。

 

下面是一个简单的例子,我们可以从程序的运行来了解条件变量的作用。

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*
初始化互斥锁*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*
初始化条件变量*/

void *thread1(void *);
void *thread2(void *);

int i=1;
int main(void)
{
    
pthread_t t_a;
    pthread_t t_b;

    pthread_create(&t_a,NULL,thread2,(void *)NULL);/*创建进程t_a*/
    
pthread_create(&t_b,NULL,thread1,(void *)NULL); /*创建进程t_b*/
    
pthread_join(t_b, NULL);/*等待进程t_b结束*/
    
pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    exit(0);
}

void *thread1(void *junk)
{
    for(i=1;i<=9;i++) 
    {
        pthread_mutex_lock(&mutex);/*锁住互斥量*/
        
if(i%3==0)
             pthread_cond_signal(&cond);/*条件改变,发送信号,通知t_b进程*/
        else        
             printf("thead1:%d/n",i);
        pthread_mutex_unlock(&mutex);/*解锁互斥量*/

sleep(1);
}

}

void *thread2(void *junk)
{
    
while(i<9)
    {
        pthread_mutex_lock(&mutex);

if(i%3!=0)
        
    pthread_cond_wait(&cond,&mutex);/*等待*/
        
printf("thread2:%d/n",i);
        pthread_mutex_unlock(&mutex);

sleep(1);
}

}

程序创建了2个新线程使他们同步运行,实现进程t_b打印20以内3的倍数,t_a打印其他的数,程序开始线程t_b不满足条件等待,线程t_a运行使a循环加1并打印。直到i为3的倍数时,线程t_a发送信号通知进程t_b,这时t_b满足条件,打印i值。

下面是运行结果:

#cc –lpthread –o cond cond.c

#./cond

thread1:1

thread1:2

thread2:3

thread1:4

thread1:5

thread2:6

thread1:7

thread1:8

thread2:9

 

 

备注:

 pthread_cond_wait 执行的流程首先将这个mutex解锁, 然后等待条件变量被唤醒, 如果没有被唤醒, 该线程将一直休眠, 也就是说, 该线程将一直阻塞在这个pthread_cond_wait调用中, 而当此线程被唤醒时, 将自动将这个mutex加锁,然后再进行条件变量判断(原因是“惊群效应”,如果是多个线程都在等待这个条件,而同时只能有一个线程进行处理,此时就必须要再次条件判断,以使只有一个线程进入临界区处理。),如果满足,则线程继续执行,最后解锁,

 

也就是说pthread_cond_wait实际上可以看作是以下几个动作的合体:
解锁线程锁
等待线程唤醒,并且条件为true
加锁线程锁.


 pthread_cond_signal仅仅负责唤醒正在阻塞在同一条件变量上的一个线程,如果存在多个线程,系统自动根据调度策略决定唤醒其中的一个线程,在多处理器上,该函数是可能同时唤醒多个线程,同时该函数与锁操作无关,解锁是由pthread_mutex_unlock(&mutex)完成

 

 

唤醒丢失问题 
在线程并没有阻塞在条件变量上时,调用pthread_cond_signal或pthread_cond_broadcast函数可能会引起唤醒丢失问题。

唤醒丢失往往会在下面的情况下发生:

一个线程调用pthread_cond_signal或pthread_cond_broadcast函数; 
另一个线程正处在测试条件变量和调用pthread_cond_wait函数之间; 
没有线程正在处在阻塞等待的状态下。

 


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384015.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UVa455

【题目描述】 传送门 【题目分析】 就是一个简单的暴力&#xff0c;只是需要注意输出格式比较毒瘤。 【AC代码】 #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include<cmath> #i…

网络相关基础概念

一. 相关基础概念 1.计算机网络的特点 (1)连通性:计算机网络使得上网的用户都能够彼此相连, 好像用户的计算机可以直接相连     (2)资源共享:资源共享可以是信息共享, 软件共享, 硬件共享等等. 由于网络的存在, 使得用户感觉资源就在自己身边 2. 网络 网络是由若干结点和…

linux线程同步(2)-条件变量

https://www.cnblogs.com/yuuyuu/p/5140875.html linux线程同步(2)-条件变量 一.概述 上一篇&#xff0c;介绍了互斥量。条件变量与互斥量不同&#xff0c;互斥量是防止多线程同时访问共享的互斥变量来保护临界区。条件变量…

UVa227

【题目描述】 传送门 【题目分析】 题目的意思很简单&#xff0c;只是输入输出很毒瘤&#xff0c;我一开始用的fgets然后用scanf(" ")吃掉所有的空格和换行&#xff0c;可是这样有可能将迷宫的空格吃掉&#xff08;例如这个空格恰好在第一行第一列&#xff09;。 …

点对点数据链路层

数据链路层的主要功能将数据转换为相应的比特流使用的信道主要有点对点的信道方式(一对一的方式), 以及广播的信道方式 一. 点对点信道的数据链路层 1. 数据链路和数据帧 链路就是从一个结点连接到相邻结点的一段物理线路(有线或者无线), 期间不准有任何的交换结点, 因此两台…

UVa232

[题目描述] 传送门 [题目分析] 简单的模拟,注意细节 [AC代码] #include<cstdio> #include<cstring> #include<algorithm> #include<climits> #include<cctype> #include<queue> #include<set>using namespace std;typedef long…

linux线程同步(1)-互斥量

http://www.cnblogs.com/yuuyuu/p/5140251.html 一.概述 互斥量是线程同步的一种机制&#xff0c;用来保护多线程的共享资源。同一时刻&#xff0c;只允许一个线程对临界区进行访问。 互斥量的工作流程&#xff1a;创建一个…

UVa1368

[题目描述] 传送门 [题目分析] 乍一看好像有点复杂,稍微思考一下只需要找到每个位置中最多的碱基.如果相等的话优先输出字典序小的. [AC代码] #include<cstdio> #include<cstring> #include<algorithm> #include<climits> #include<cctype>…

linux线程同步(3)-读写锁

http://www.cnblogs.com/yuuyuu/p/5143881.html 一.概述 读写锁与互斥量的功能类似&#xff0c;对临界区的共享资源进行保护&#xff01;互斥量一次只让一个线程进入临界区&#xff0c;读写锁比它有更高的并行性。读写锁有…

树的相关笔试面试题

1. 树的创建 已知一个先序遍历数的结果用数组表示, 其中空节点用 null_node 表示, 要求创建出这棵树. 同样采用递归的思想, 先定义一个指针, 指向数组中的第一个元素, 然后给数组的第一个结点创建相应的结点, 然后指针后移, 递归创建根节点的左子树, 递归创建根节点的右子树, …

UVa202

[题目描述] 传送门 [题目分析] 就是一个模拟,不过稍微有点小复杂,而且输出格式有点小毒瘤. 不过只是RE了两发,PE了一发就过了,还是很开心. 需要注意数组要开很大,可能循环节出现在很后. 每个输出样例应该输出一个空行,最后面也应该有,不然会PE [AC代码] #include<cst…

linux线程同步(5)-屏障

http://www.cnblogs.com/yuuyuu/p/5152560.html 一.概述 barrier(屏障)与互斥量&#xff0c;读写锁&#xff0c;自旋锁不同&#xff0c;它不是用来保护临界区的。相反&#xff0c;它跟条件变量一样&#xff0c;是用来协同多…

浅谈软件测试

一. 什么是软件测试 软件测试是一个过程或者一系列过程, 用来测试计算机代码完成了其应该完成的功能, 不执行不该有的操作.或者说软件测试是根据软件开发各阶段的功能和说明而精心设计的一批测试用例, 并根据测试用例运行程序, 以发现程序错误的过程. 二. 软件测试的心理学和…

UVa10340

【题目描述】 传送门 【题目分析】 求字串&#xff0c;最好还是处理母串&#xff0c;每次找到一个子串就加1&#xff0c;这样处理不用处理细节 【AC代码】 #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include&l…

浅析linux下的条件变量

一.条件变量 条件变量是用来等待线程而不是上锁的&#xff0c;条件变量通常和互斥锁一起使用。条件变量之所以要和互斥锁一起使用&#xff0c;主要是因为互斥锁的一个明显的特点就是它只有两种状态&#xff1a;锁定和非锁定&#xff0c;而条件变量可以通过允许线程阻塞和等待另…

UVa1587

【题目描述】 传送门 【题目分析】 刚开始想简单了&#xff0c;认为只要相对的面相等就可以了。然后发现三个不同方向的面的边应该有相等的关系&#xff0c;即如果两个面公用一条边&#xff0c;那么这两个面的另外两条边就是另一个面的两条边。而且这三个量里面肯定有一个最…

Linux多线程与同步

https://www.cnblogs.com/freedomabcd/p/7774743.html 典型的UNIX系统都支持一个进程创建多个线程(thread)。在Linux进程基础中提到&#xff0c;Linux以进程为单位组织操作&#xff0c;Linux中的线程也都基于进程。尽管实现方式有异于其它的UNIX系统&#xff0c;但Linux的多线程…

内存管理(二)

页面置换算法 当发生缺页中断的时候, 系统会在内存中选择一个页面将其换出内存, 而当换出内存的时候如果该页面的内容在内存中发生修改,则必须将该新数据重新写回到磁盘, 然后再将需要换进的数据覆盖掉原来的数据, 而当该数据在内存中没有被修改的时候, 此时就直接用需要换进的…

两个栈实现一个队列/两个队列实现一个栈

http://blog.csdn.net/sinat_30472685/article/details/70157227 1两个栈实现一个队列 1.原理分析&#xff1a; 队列的主要操作有两个&#xff1a;入队操作和出队操作&#xff0c;出队时从队头出&#xff0c;入队是从队尾插入&#xff0c;入队的操作和入栈的操作类似&#xff0…

UVa1588

【题目描述】 传送门 【题目分析】 刚开始想了一会没有想到什么很好的算法&#xff0c;看到了长度最多为100&#xff0c;就知道自己想的没有什么意义了&#xff0c;直接暴力&#xff0c;把每一种填法都试一下就知道了。适当剪枝一下&#xff08;一个简单的乐观函数&#xff…