互斥锁:用来上锁。

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

函数介绍:

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函数之间;
没有线程正在处在阻塞等待的状态下。

Linux 线程学习之条件变量相关推荐

  1. Linux线程同步之条件变量

    与互斥锁不同,条件变量是用来等待而不是用来上锁的.条件变量用来自动阻塞一个线程,直到某特殊情况发生为止.通常条件变量和互斥锁同时使用. 条件变量使我们可以睡眠等待某种条件出现.条件变量是利用线程间共享 ...

  2. [转]Linux线程同步之条件变量

    与互斥锁不同,条件变量是用来等待而不是用来上锁的.条件变量用来自动阻塞一个线程,直到某特殊情况发生为止.通常条件变量和互斥锁同时使用. 条件变量使我们可以睡眠等待某种条件出现.条件变量是利用线程间共享 ...

  3. Linux——线程同步(条件变量、POSIX信号量)和线程池

    一.线程同步 (一).概念 线程同步是一种多线程关系,指的是线程之间按照特定顺序访问临界资源,进而能够避免线程饥饿问题. 所谓线程饥饿指的是某个线程长期"霸占"临界资源,导致其他线 ...

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

    一.概述                                                    上一篇,介绍了互斥量.条件变量与互斥量不同,互斥量是防止多线程同时访问共享的互斥变量来保 ...

  5. linux 条件变量函数,Linux线程同步之条件变量

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

  6. 线程同步之条件变量:pthread_cond_signal和pthread_cond_wait

    在多线程编程下,常常出现A线程要等待B线程条件完成后再继续进行,这里等待方式有两种: 1.使用锁+轮询 使用这种方法可以很简单的实现,但是会有一定的性能消耗,其还有一个点要好好把握,就是一次轮询没有结 ...

  7. 【牛客网C++服务器项目学习】Day8-线程相关、线程锁、条件变量、信号量

    项目学习地址:[牛客网C++服务器项目学习] day08 函数:void pthread_exit(void *retval); 功能:终止调用这个函数的线程.如果是一个进程的最后一个线程调用该函数, ...

  8. C++多线程学习(三)——线程同步之条件变量

    前面学习了互斥量似乎我们就可以多线程编程了,多线程也不过如此嘛.然而我们上手coding,用多线程来结局我们实际需求就会发现,似乎多线程也不是很好用.因为我们实际对于多线程的需求,往往线程都是whil ...

  9. Linux系统编程38:多线程之什么是线程同步以及条件变量函数

    文章目录 (1):什么是线程的同步 (2):实现线程同步-条件变量函数 (1):什么是线程的同步 假如有一片临界资源,线程A和B都会修改它,为了保护资源所以要加锁,此时它们之间是互斥的关系.在我们的代 ...

最新文章

  1. Nginx 学习笔记(六)引入线程池 性能提升9倍
  2. (四)Thymeleaf标准表达式之——[3-6] 操作符(文本、算术、布尔、比较及相等)...
  3. SQL server 数据库——T-SQL语句基础
  4. IP修改器的作用以及用途
  5. 解决Webview加载不完全导致部分js无效
  6. django (三) admin后台系统
  7. LA 3942 Remember the Word
  8. “弱肉强食,月半者为王” | OpenDILab推出多智能体博弈环境Go-Bigger
  9. ubantu安装mysql卡住_ubuntu安装mysql遇到的问题
  10. 单片机与普通微型计算机不同在于,单片机与普通计算机的不同之处在于什么,单片机与普通微型计算机的不同...
  11. python创建矩阵_Python创建二维数组的正确姿势
  12. Win7系统下发生一个文件夹,无法删除,解决记录
  13. 【Vue 组件化开发 三】父组件给子组件传递数据、组件通信(父传子、子传父)、父访问子(children、ref)、动态组件(is、component)
  14. getAnnotation(Class.class) 为空问题
  15. Markdown KeTex 德尔塔等于符
  16. 华为可以更新鸿蒙系统,华为手机如何升级鸿蒙系统 步骤如下
  17. 软件 ce ee 含义和区别
  18. spring boot spring data 整合 redis redis keys * 出现 \xac\xed\x00\x05t\x00) 编码异常
  19. Python打包exe瘦身方法
  20. 青柠网络验证远程api使用方法

热门文章

  1. 计算长方形的周长和面积(类和对象)_JAVA
  2. 【Linux】44.设置ubuntu电脑为简单的密码
  3. Stanford机器学习笔记-6. 学习模型的评估和选择
  4. AbstractQueuedSynchronizer 原理分析 - 独占/共享模式
  5. Java 程序中的多线程
  6. 虚拟化的发展历程和实现原理——图文详解
  7. java的mock测试框架
  8. 浅淡Webservice、WSDL三种服务访问的方式(附案例)
  9. OpenCV学习笔记(四十一)——再看基础数据结构core OpenCV学习笔记(四十二)——Mat数据操作之普通青年、文艺青年、暴力青年 OpenCV学习笔记(四十三)——存取像素值操作汇总co
  10. 深度学习(二十五)基于Mutil-Scale CNN的图片语义分割、法向量估计-ICCV 2015