linux条件变量知识点总结

news2024/12/27 14:06:25

与条件变量相关API

    条件变量是线程另一可用的同步机制。条件变量给多个线程提供了一个会合的场所。条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定的条件发生。

  条件本身是由互斥量保护的。线程在改变条件状态前必须首先锁住互斥量,其他线程在获得互斥量之前不会察觉到这种改变,因为必须锁定互斥量以后才能计算条件。

  条件变量使用之前必须首先初始化,pthread_cond_t数据类型代表的条件变量可以用两种方式进行初始化,可以把常量PTHREAD_COND_INITIALIZER赋给静态分配的条件变量,但是如果条件变量是动态分配的,可以使用pthread_cond_destroy函数对条件变量进行去除初始化(deinitialize)。

1. 创建及销毁条件变量

#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);
// 返回:若成功返回0,否则返回错误编号

  除非需要创建一个非默认属性的条件变量,否则pthread_cont_init函数的attr参数可以设置为NULL。

2. 等待

#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, cond struct timespec *restrict timeout);
// 返回:若成功返回0,否则返回错误编号

  pthread_cond_wait等待条件变为真。如果在给定的时间内条件不能满足,那么会生成一个代表一个出错码的返回变量。传递给pthread_cond_wait的互斥量对条件进行保护,调用者把锁住的互斥量传给函数。函数把调用线程放到等待条件的线程列表上,然后对互斥量解锁,这两个操作都是原子操作。这样就关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的时间通道,这样线程就不会错过条件的任何变化。pthread_cond_wait返回时,互斥量再次被锁住。

  pthread_cond_timedwait函数的工作方式与pthread_cond_wait函数类似,只是多了一个timeout。timeout指定了等待的时间,它是通过timespec结构指定。

3. 触发

#include <pthread.h>
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
// 返回:若成功返回0,否则返回错误编号

  这两个函数可以用于通知线程条件已经满足。pthread_cond_signal函数将唤醒等待该条件的某个线程,而pthread_cond_broadcast函数将唤醒等待该条件的所有进程。

  注意一定要在改变条件状态以后再给线程发信号。

Linux线程开发中,通常对于互斥量、条件变量等都会提供两种初始化方式,分别是动态初始化和静态初始化。

一般来说变量的静态初始是预编译时对变量进行初始化,而动态初始,是在程序运行时,根据需要,动态分配空间并赋值

如:
pthread cond t cond;
//动态初始化: pthread cond init(&cond,NULL);
/静态初始化: pthread cond t = PTHREAD COND INITIALIZER;

pthread mutex_t;
//动态初始化: pthread mutex init(&mutex,NULL);
//静态初始化: pthread mutex tT= PTHREAD MUTEX INITIALIZER;

示例

(1)线程条件控制实现线程同步(动态初始化)

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

//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
int g_data = 0;

pthread_mutex_t mutex;
pthread_cond_t cond;

void *func1(void *arg)
{
    printf("t1:%ld thread is create\n",(unsigned long)pthread_self());
    printf("t1:param is %d\n",*((int *)arg));
    static int cnt = 0;
    
    while(1){
        
        pthread_cond_wait(&cond,&mutex);
        printf("t1 run================================\n");

        printf("t1: %d\n",g_data);    
        g_data = 0;
        sleep(1);
        if(cnt++ == 10){
            exit(1);
        }
    }

}

void *func2(void *arg)
{
    printf("t2:%ld thread is create\n",(unsigned long)pthread_self());
    printf("t2:param is %d\n",*((int *)arg));
    
    
    while(1){

        printf("t2: %d\n",g_data);
        pthread_mutex_lock(&mutex);
        g_data++;
        if(g_data == 3){
            pthread_cond_signal(&cond);
        }
        pthread_mutex_unlock(&mutex);    
        sleep(1);
    }
}

int main()
{
    int ret;
    int param = 100;
    pthread_t t1;
    pthread_t t2;

    //动态初始化
    pthread_mutex_init(&mutex,NULL);
    pthread_cond_init(&cond,NULL);


    ret = pthread_create(&t1, NULL, func1,(void *)&param);
    if(ret == 0){
//        printf("main:create t1 success\n");
    }

    ret = pthread_create(&t2, NULL, func2,(void *)&param);
    if(ret == 0){
//        printf("main:create t2 success\n");
    }

//    printf("main:%ld\n",(unsigned long)pthread_self());

    pthread_join(t1,NULL);
    pthread_join(t2,NULL);

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    return 0;
}

编译结果:

(2)线程条件控制实现线程同步(静态初始化)

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

//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
int g_data = 0;

//静态初始化
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void *func1(void *arg)
{
    printf("t1:%ld thread is create\n",(unsigned long)pthread_self());
    printf("t1:param is %d\n",*((int *)arg));
    static int cnt = 0;
    
    while(1){
        
        pthread_cond_wait(&cond,&mutex);
        printf("t1 run================================\n");

        printf("t1: %d\n",g_data);    
        g_data = 0;
        sleep(1);
        if(cnt++ == 10){
            exit(1);
        }
    }

}

void *func2(void *arg)
{
    printf("t2:%ld thread is create\n",(unsigned long)pthread_self());
    printf("t2:param is %d\n",*((int *)arg));
    
    
    while(1){

        printf("t2: %d\n",g_data);
        pthread_mutex_lock(&mutex);
        g_data++;
        if(g_data == 3){
            pthread_cond_signal(&cond);
        }
        pthread_mutex_unlock(&mutex);    
        sleep(1);
    }
}

int main()
{
    int ret;
    int param = 100;
    pthread_t t1;
    pthread_t t2;

//动态初始化
//    pthread_mutex_init(&mutex,NULL);
//    pthread_cond_init(&cond,NULL);


    ret = pthread_create(&t1, NULL, func1,(void *)&param);
    if(ret == 0){
//        printf("main:create t1 success\n");
    }

    ret = pthread_create(&t2, NULL, func2,(void *)&param);
    if(ret == 0){
//        printf("main:create t2 success\n");
    }

//    printf("main:%ld\n",(unsigned long)pthread_self());

    pthread_join(t1,NULL);
    pthread_join(t2,NULL);

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    return 0;
}


编译结果:与上面一样

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

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

相关文章

chatgpt赋能python:Python中的“5“+“5“:了解运算符重载和字符串拼接

Python中的 “5”“5”: 了解运算符重载和字符串拼接 Python中的运算符重载允许我们自定义类型的操作符行为。当我们使用加号运算符将两个对象相加时&#xff0c;Python会动态地确定该使用哪种类型的操作符行为。在使用字符串时&#xff0c;加号可以用于字符串的连接&#xff…

【编译、链接、装载二】/lib/ld64.so.1: bad ELF interpreter: 没有那个文件或目录

【编译和链接二】bash: ./test.out: /lib/ld64.so.1: bad ELF interpreter: 没有那个文件或目录 一、问题起因二、ldd查看三、解决方案一&#xff1a;使用gcc链接四、查找其他解决方案五、解决方案二&#xff1a;软链接 bash: ./test.out: /lib/ld64.so.1: bad ELF interpreter…

SpringBoot框架总结

一、SpringBoot框架的概念 1、传统框架的弊端 例如传统的SSM框架整合了MyBatis、Spring、SpringMVC框架&#xff0c;但其需要繁琐且重复的配置使程序员很是痛苦 2、SpringBoot框架 SpringBoot框架在传统框架的基础上对其进一步封装&#xff0c;只需要一些简单的配置&#x…

MySQL第二章、数据库基础

回顾&#xff1a; 目录 一、数据库的操作 1.1创建数据库 1.2显示当前数据库 1.3使用数据库 1.4删除数据库 二、常用数据类型 2.1数值类型&#xff08;分为整型和浮点型&#xff09; 2.2字符串类型 2.3 日期类型 三、表的操作 ​编辑 3.1创建表 3.2查看表结构 ​编…

网络攻防技术--论文阅读--《基于自动数据分割和注意力LSTM-CNN的准周期时间序列异常检测》

英文题目&#xff1a;Anomaly Detection in Quasi-Periodic Time Series based on Automatic Data Segmentation and Attentional LSTM-CNN 论文地址&#xff1a;Anomaly Detection in Quasi-Periodic Time Series Based on Automatic Data Segmentation and Attentional LST…

chatgpt赋能python:Python中清空代码的几种方法

Python中清空代码的几种方法 在Python编程中&#xff0c;清空代码是一个很常见的需求。清空代码指的是在某些情况下&#xff0c;需要将已经定义的变量或内存中存储的对象清除&#xff0c;以便后续使用。在本文中&#xff0c;我们将介绍Python中常用的几种清空代码的方法。 方…

chatgpt赋能python:Python中等待几秒代码:让你的程序更高效

Python中等待几秒代码&#xff1a;让你的程序更高效 在编写Python程序时&#xff0c;有时我们需要让程序等待几秒钟之后再继续执行。这个操作非常常见&#xff0c;尤其是在需要与API接口交互的时候。在本文中&#xff0c;我们将会介绍Python语言中等待几秒的相关知识&#xff…

如何使用Kali进行信息收集?

渗透测试即模拟黑客入侵的手段对目标网络进修安全测试&#xff0c;从而发现目标网络的漏洞&#xff0c;对目标网络进行安全加固与漏洞修复。 Kali 是一个基于 debian 的渗透测试平台&#xff0c;其中集成了很多常见的和不常见的渗透测试工具&#xff0c;如下图&#xff1a; 工…

linux(SystemV标准)进程间通信1

目录&#xff1a; 1.前言 2.共享内存 3.认识接口 ------------------------------------------------------------------------------------------------------------------------- 1.前言 我们之前学的什么匿名管道、命名管道通信都是基于文件的通信方式&#xff01;&#xf…

chatgpt赋能python:Python中的%怎么用

Python中的%怎么用 Python中的%是一个非常重要的运算符&#xff0c;也称为格式化运算符。它用于将一个值插入到另一个字符串中。在本文中&#xff0c;我们将深入了解Python中的%运算符的使用。 %运算符的语法 先看下%运算符的语法&#xff1a; string % values其中&#xf…

求图的最短路径长度的弗洛伊德(Floyd)算法

弗洛伊德算法的适用情况&#xff1a;弗洛伊德算法既可以用来求解有向网的最短路径长度&#xff0c;也可以用来求无向网的最短路径长度&#xff0c;但是对于图中出现负权环的情况&#xff0c;弗洛伊德无法的得到正确的答案 弗洛伊德的算法思想&#xff1a; 以此图为例讲解弗洛…

C语言杂七杂八

fget函数的用法 fgets() 函数用来从指定的文件中读取一个字符串&#xff0c;并保存到字符数组中。 str 为字符数组&#xff0c;n 为要读取的字符数目&#xff0c;fp 为文件指针。 char *fgets(char *str, int n, FILE *stream) 返回值&#xff1a;读取成功时返回字符数组首地…

python图像处理实战(一)—图像基础

&#x1f680;写在前面&#x1f680; &#x1f58a;个人主页&#xff1a;https://blog.csdn.net/m0_52051577?typeblog &#x1f381;欢迎各位大佬支持点赞收藏&#xff0c;三连必回&#xff01;&#xff01; &#x1f508;本人新开系列专栏—python图像处理 ❀愿每一个骤雨初…

Android12之service调试(一百五十二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

C4D R26 渲染学习笔记 建模篇(3):生成器

文章目录 前文回顾介绍篇建模篇 生成器介绍生成器变形器搭配举例 生成器详细介绍细分曲面布料曲面 未完待续 前文回顾 介绍篇 C4D R26 渲染学习笔记&#xff08;1&#xff09;&#xff1a;C4D版本选择和初始UI框介绍 C4D R26 渲染学习笔记&#xff08;2&#xff09;&#xff…

微服务Spring Cloud 02------使用Eureka实现注册中心(1)

1.Eureka简介 Eureka是Spring Cloud中的一个负责服务注册与发现的组件。遵循着CAP理论中的A(可用性)和P(分区容错性)。 Eureka是Netflix中的一个开源框架。它和 Zookeeper、Consul一样&#xff0c;都是用于服务注册管理的&#xff0c;同样&#xff0c;Spring-Cloud 还集成了Zo…

Canvas画布基本功能及实现网页签名功能

canvas 简介 <canvas> 是 HTML5 新增的&#xff0c;一个可以使用脚本(通常为 JavaScript) 在其中绘制图像的 HTML 元素。它可以用来制作照片集或者制作简单(也不是那么简单)的动画&#xff0c;甚至可以进行实时视频处理和渲染。和所有 DOM 元素一样&#xff0c;拥有自己…

chatgpt赋能python:Python中累乘的作用和用法

Python中累乘的作用和用法 在Python编程语言中&#xff0c;累乘指的是连续乘法&#xff0c;或者说是一系列数字的乘积。累乘的概念非常简单&#xff0c;但是实际上它在编程中有着广泛的应用。 累乘在Python中的实现方式 Python中&#xff0c;累乘可以通过多种方式来实现&…

手写一个webpack插件(plugin)

熟悉 vue 和 react 的小伙伴们都知道&#xff0c;在执行过程中会有各种生命周期钩子&#xff0c;其实webpack也不例外&#xff0c;在使用webpack的时候&#xff0c;我们有时候需要在 webpack 构建流程中引入自定义的行为&#xff0c;这个时候就可以在 hooks 钩子中添加自己的方…

使用docker和minio实现对象存储

文章目录 使用docker和minio实现对象存储什么是minio安装minio使用minio 使用docker和minio实现对象存储 什么是minio ​ Minio是一个开源的分布式文件存储系统&#xff0c;它基于 Golang 编写,虽然轻量&#xff0c;却拥有着不错的高性能&#xff0c;可以将图片、视频、音乐、…