Linux多线程[二]

news2025/1/18 4:47:33
线程同步

一个资源,我们不知道他是不是准备好了资源,就需要频繁申请。这时候对于这个执行流,多次检测,极大的浪费了资源。而且对于资源来说一个线程多次申请资源的时候,他一直申请到资源,别的线程申请不到资源,就造成了线程饥饿。所以就有了线程同步的概念。为了解决访问临界资源合理性问题。应该让一个资源申请之后,不能再次被同一个执行流申请,新来的也得排队。让资源访问具有顺序性。

那么什么叫同步?

按照一定的顺序,进行资源的访问,就叫做线程的同步。同时线程对于资源的申请不要频繁的询问,当资源准备好之后会发消息通知的。

1.条件变量

在申请临界资源之前,先要做临界资源的检测,有没有。检测的本质其实对临界资源的访问,那么对于临界资源的检测也是需要加锁和解锁的。常规方式的检测条件就绪,注定了要频繁申请释放锁。[申请到锁不意味着资源是就绪的]那么有没有办法让线程检测到资源不就绪的时候不要频繁的检测,等待。当条件就绪的时候,通知对应的线程进行资源的访问。所以要引入条件变量。

  • 当一个线程互斥地访问某个变量时,它可能发现在其它线程改变状态之前,它什么也做不了。
  • 例如一个线程访问队列时,发现队列为空,它只能等待,只到其它线程将一个节点添加到队列中。这种情 况就需要用到条件变量。
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
参数:
    cond:要初始化的条件变量
    attr:NULL

 这是动态分配的条件变量初始化

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

这个是静态分配条件变量初始化。

对于没有就绪的资源等待

int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
    参数:
        cond:要在这个条件变量上等待
        mutex:互斥量,后面详细解释

资源就绪唤醒线程

 int pthread_cond_broadcast(pthread_cond_t *cond);//全部唤醒线程
   int pthread_cond_signal(pthread_cond_t *cond);//按照书顺序唤醒一个线程

  wait是在加锁和解锁之间的wait 检测临界资源就绪一定在临界资源内等待。

示例demo

#include<iostream>
#include<pthread.h>
#include<string>
#include<cstdio>
#include<unistd.h>
using namespace std;


#define Thread_NUM 4


typedef void(*func_t)( string &name,pthread_mutex_t* mtx,pthread_cond_t*cond);
volatile bool quit =false;


class Thread_date
{
    public:
    Thread_date( string &name,func_t func,pthread_mutex_t* mtx,pthread_cond_t*cond):name_(name),func_(func),ptmux(mtx),ptcond(cond)
    {

    }
    public:
    string name_;
    func_t func_;
    pthread_mutex_t *ptmux;
    pthread_cond_t *ptcond;
};

void func1(string &name,pthread_mutex_t* mtx,pthread_cond_t*cond)
{
    while(!quit)
    {
                //加锁
        pthread_mutex_lock(mtx);
        pthread_cond_wait(cond,mtx);//默认该线程在支持的时候wait代码被执行,当前线程立马被阻塞。
        //将线程放到队列中等待。
        cout<<name<<" runing......a"<<endl;
pthread_mutex_unlock(mtx);
    }
}
void func2(string &name,pthread_mutex_t* mtx,pthread_cond_t*cond)
{
    while(!quit)
    {
                //加锁
        pthread_mutex_lock(mtx);
         pthread_cond_wait(cond,mtx);//默认该线程在支持的时候wait代码被执行,当前线程立马被阻塞。
        cout<<name<<" runing......b"<<endl;
pthread_mutex_unlock(mtx);
    }
}void func3(string &name,pthread_mutex_t* mtx,pthread_cond_t*cond)
{
    while(!quit)
    {
                //加锁
        pthread_mutex_lock(mtx);
         pthread_cond_wait(cond,mtx);//默认该线程在支持的时候wait代码被执行,当前线程立马被阻塞。
        cout<<name<<" runing......c"<<endl;
pthread_mutex_unlock(mtx);
    }
}void func4(string &name,pthread_mutex_t* mtx,pthread_cond_t*cond)
{
    while(!quit)
    {
        //wait不少这样子用的  wait是在加锁和解锁之间的wait 检测临界资源就绪一定在临界资源内等待

        //加锁
        pthread_mutex_lock(mtx);
         pthread_cond_wait(cond,mtx);//默认该线程在支持的时候wait代码被执行,当前线程立马被阻塞。在临界资源内等待
        cout<<name<<" runing......d"<<endl;
        pthread_mutex_unlock(mtx);

    }
}

 void *Entry(void*args)
 {
     Thread_date*fd =(Thread_date*)args;
     fd->func_(fd->name_,fd->ptmux,fd->ptcond);
     delete fd;
     return nullptr;
 }
int main()
{
    pthread_t tid[Thread_NUM];
    pthread_mutex_t mux;//创建锁
    pthread_cond_t cond;//创建条件变量
    pthread_mutex_init(&mux,nullptr);
    pthread_cond_init(&cond,nullptr);//初始化条件变量。
    func_t funcs[Thread_NUM] = {func1, func2, func3, func4};
    for(int i=0;i<Thread_NUM;i++)
    {
        string name="thread ---";
        name+=to_string(i+1);
        Thread_date*td =new Thread_date(name,funcs[i],&mux,&cond);//条件传递 锁和条件变量
        pthread_create(tid+i,nullptr,Entry,(void*)td);
    }
        sleep(2);
    //尝试唤醒新线程
    int cun =10;
    while(1)
    {
        cout<<"唤醒线程中---------------cnt"<<cun--<<".............";
        pthread_cond_signal(&cond);//唤醒条件变量
        sleep(1);
    }

    quit =true;

    for(int i=0;i<Thread_NUM;i++)

    {
        pthread_join(tid[i],nullptr);
        cout<<"线程----"<<i<<"退出成功"<<endl;
    }
    pthread_mutex_destroy(&mux);//释放锁
    pthread_cond_destroy(&cond);//销毁条件变量
    return 0;
}   
2.生产者消费者模型

为何要使用生产者消费者模型
生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理, 直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了 生产者和消费者的处理能力。这个阻塞队列就是用来给生产者和消费者解耦的。

 生产者和生产者之间是互斥关系,消费者和消费者之间是竞争,互斥关系。生产者和消费者是互斥/同步关系(生产完再消费,消费完再生产)。遵循321原则。给线程角色化,承担不同的角色,而中间的超市本质上数据结构形成的缓冲区,商品是数据。某种意义进程间通信就是生产者,消费者模型。 

那么多生产和多消费意义在哪里?可以让生产和消费有多个执行流进行生产和消费。

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

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

相关文章

debug - 打补丁 - 浮点数加法

文章目录 debug - 打补丁 - 浮点数加法概述笔记demo用CE查看汇编(x64debug)main()update_info()快捷键 - CE中查看代码时的导航打补丁的时机 - 浮点数加法补丁代码补丁效果浮点数寄存器组的保存END debug - 打补丁 - 浮点数加法 概述 在cm中, UI上显示的数值仅仅用来显示, 改…

微信公众号怎么做收集信息功能_轻松打造信息收集神器

微信公众号&#xff1a;轻松打造信息收集神器&#xff0c;让您的业务更上一层楼&#xff01; 在数字化时代&#xff0c;信息的传递与收集已成为企业和个人成功的关键。微信&#xff0c;作为中国最大的社交平台之一&#xff0c;其公众号功能为企业和个人提供了一个绝佳的信息收…

第三百四十七回

文章目录 1. 概念介绍2. 原理与方法2.1 知识对比2.2 使用方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"加密包crypto"相关的内容&#xff0c;本章回中将介绍characters包.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 在项目中会遇到获取字…

2024年【起重机司机(限门式起重机)】考试及起重机司机(限门式起重机)模拟考试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 起重机司机(限门式起重机)考试是安全生产模拟考试一点通总题库中生成的一套起重机司机(限门式起重机)模拟考试题&#xff0c;安全生产模拟考试一点通上起重机司机(限门式起重机)作业手机同步练习。2024年【起重机司机…

第13章 网络 Page734 “I/O对象”的链式传递 单独的火箭发射函数,没有用对的智能指针

上一篇博文中&#xff0c;我们使用单独的火箭发射函数&#xff0c;结果什么结果也没有得到&#xff0c;原因是launch_rocket()函数结束时&#xff0c;其内的局部对象counter生命周期也结束了 那么可以将counter改为指针吗&#xff1f;在堆中分配&#xff0c;这样当函数退出时&…

SpringBoot+Tess4J实现本地与远程图片的文字识别

Spring Boot应用程序里集成Tess4J来实现OCR&#xff08;光学字符识别&#xff09;&#xff0c;以识别出本地和远程图片中的文字 一、添加依赖 <dependency><groupId>net.sourceforge.tess4j</groupId><artifactId>tess4j</artifactId><vers…

基于Echarts的可视化项目

整体的效果 概览区域 <!-- 概览区域模块制作 --><div class"panel overview"><div class"inner"><ul><li><h4>2190</h4><span><i class"icon-dot"></i>设备总数</span></…

洛谷C++简单题小练习day12—寻找最小值小程序

day12--寻找最小值--2.16 习题概述 题目描述 给出 n 和 n 个整数 ai​&#xff0c;求这 n 个整数中最小值是什么。 输入格式 第一行输入一个正整数 n&#xff0c;表示数字个数。 第二行输入 n 个非负整数&#xff0c;表示 1,2…a1​,a2​…an​&#xff0c;以空格隔开。 …

Android ·移动应用开发 创建第一个Android项目

文章目录 一、创建第一个Android项目1.1 准备好Android Studio1.2 运行程序1.3 程序结构是什么app下的结构res - 子目录&#xff08;所有图片、布局、字符串等资源&#xff09;AndroidManifest.xml 有四大组件&#xff0c;程序添加权限声明 Project下的结构 二、开发android时&…

极市平台 | 16个图像分类方向开源数据集资源汇总(附下载链接,建议收藏!)

本文来源公众号“极市平台”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;16个图像分类方向开源数据集资源汇总&#xff08;附下载链接&#xff09; 本文汇总了16个图像分类相关的开源数据集&#xff0c;均附有下载链接。要构建…

苹果手机计算器怎么进行快速删除(退格)?

文章目录 前言方法 前言 总所周知&#xff0c;不论是学生、商人&#xff0c;还是工人&#xff0c;都必须使用计算器。其中&#xff0c;苹果手机的自带计算器&#xff0c;因为完美的环境&#xff0c;所以受到大多数人的喜爱&#xff0c;使用率极高。但是&#xff0c;苹果计算器…

嵌入式Linux网络编程入门:轻松构建网络通信

大家好&#xff0c;今天给大家介绍嵌入式Linux网络编程入门&#xff1a;轻松构建网络通信&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 为什么选择嵌入式Linux网络编程&#x…

Git快速掌握,通俗易懂

Git分布式版本控制工具 介绍 Git是一个开源的分布式版本控制系统&#xff0c;用于敏捷高效地处理任何或小或大的项目。Git是由Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。Git可以帮助开发者们管理代码的版本&#xff0c;避免代码冲突&#…

RabbitMQ配置消息转换器

1. 默认转换器 Test public void testSendMap() throws InterruptedException {// 准备消息Map<String, Object> msg new HashMap<>();msg.put("name", "harry");msg.put("age", 21);// 发送消息rabbitTemplate.convertAndSend(&q…

FreeRTOS知识点

1>任务调度算法 1.抢占式调度&#xff1a;高优先级的任务优先执行&#xff0c;并且可以打断低优先级的任务执行。 在FreeRTOSConfig.h中开启configUSE_PREEMPTION宏&#xff0c;将宏设置为1&#xff0c;关闭&#xff08;将宏设置为0&#xff09; 2.时间片轮转&#xff1a…

什么是 Flet?

什么是 Flet&#xff1f; Flet 是一个框架&#xff0c;允许使用您喜欢的语言构建交互式多用户 Web、桌面和移动应用程序&#xff0c;而无需前端开发经验。 您可以使用基于 Google 的 Flutter 的 Flet 控件为程序构建 UI。Flet 不只是“包装”Flutter 小部件&#xff0c;而是…

Repo命令使用实例(三十八)

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

动态多目标优化算法基准测试问题JY

论文题目&#xff1a;Evolutionary Dynamic Multiobjective Optimization: Benchmarks and Algorithm Comparisons 进化动态多目标优化&#xff1a;基准测试和算法比较&#xff08;Shouyong Jiang and Shengxiang Yang, Senior Member, IEEE&#xff09;IEEE TRANSACTIONS ON …

【UE4】 通过按钮点击实现摄像机的切换 并通过鼠标控制新摄像机的旋转

效果 步骤 首先创建了4个Actor蓝图类 每个蓝图类内只拥有一个摄像机组件 将每个actor蓝图类摆放到场景的合适位置 在关卡蓝图中创建自定义事件&#xff0c;当该事件触发时切换摄像机 创建一个控件蓝图&#xff0c;在控件蓝图中创建如下5个按钮&#xff0c;并创建点击事件。按钮…

基于HTML5实现动态烟花秀效果(含音效和文字)实战

目录 前言 一、烟花秀效果功能分解 1、功能分解 2、界面分解 二、HTML功能实现 1、html界面设计 2、背景音乐和燃放触发 3、燃放控制 4、对联展示 5、脚本引用即文本展示 三、脚本调用及实现 1、烟花燃放 2、燃放响应 3、烟花canvas创建 4、燃放声音控制 5、实际…