Linux多线程之线程同步

(。・∀・)ノ゙嗨!你好这里是ky233的主页:这里是ky233的主页,欢迎光临~icon-default.png?t=N7T8https://blog.csdn.net/ky233?type=blog

点个关注不迷路⌯'▾'⌯

目录

一、线程同步的概念

二、条件变量

1.概念

2.接口

1.pthread_cond_init

2.pthread_cond_wait

3.pthread_cond_signal

3.代码演示


一、线程同步的概念

在我们的抢票代码中,会出现某一个线程一直在抢票的时候,这虽然没错,但是这是不合理的

  • 会频繁的申请到资源,让别人没办法
  • 会让其他线程一直在轮询检测,太过于浪费资源了
  • 会造成别人饥饿的问题

所以我们就要引入线程同步

主要是为了解决,访问临界资源合理性问题的!

按照一定的顺序,进行临界资源的访问,叫做线程同步!

二、条件变量

1.概念

当我们申请临界资源前,要先对临界资源做检测,做检测的本质也是访问临界资源!

所以结论,对临界资源的检测,也是一定是需要在加锁和解锁之间的!所以,常规方式要检测条件是否就绪,就注定了我们要频繁的申请和释放锁!

那么有没有办法让我们的线程不这样做呢?

  • 让我们的线程不要频繁的自己检测,让他进行等待
  • 当条件就绪的时候,通知我们的线程,这时候再进行资源的申请和访问!
  • 所以我们的条件变量就诞生了!

2.接口

1.pthread_cond_init
int pthread_cond_init(pthread_cond_t *restrict cond,
              const pthread_condattr_t *restrict attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

全局的或静态的和互斥锁是一样的!

  • 参数一:要初始化的条件变量
  • 参数二:一些属性,目前设置为nullptr
  • 用来条件变量的初始化
2.pthread_cond_wait
int pthread_cond_wait(pthread_cond_t *restrict cond,
              pthread_mutex_t *restrict mutex);
  • 参数一:等待某种条件
  • 参数二:是一把锁,为了保证我们临界资源安全的一把锁
  • 用于等待条件满足
3.pthread_cond_signal
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
  • 有两个接口
  • 第一个:可能不止有一个资源在等资源就绪,把所有线程全部唤醒
  • 第二个:代表的是唤醒指定的线程

注意:以上接口返回值全都是成功为0,失败为错误码

3.代码演示

#define TNUM 4
typedef void (*func_t)(const string &name,pthread_mutex_t *pmtx,pthread_cond_t *pcond);
volatile bool quit =false;

class ThreadDate
{
public:
    ThreadDate(const string &name, func_t func,pthread_mutex_t *pmtx,pthread_cond_t *pcond)
        : name_(name), func_(func), pmtx_(pmtx),pcond_(pcond) 
    {
    }
    string name_;
    func_t func_;
    pthread_mutex_t *pmtx_;
    pthread_cond_t *pcond_;
    };

void func1(const string &name,pthread_mutex_t *pmtx,pthread_cond_t *pcond)
{
   while(!quit)
    {
        //wait一定要在加锁和解锁之间wait,这是因为我们需要检测临界资源是否就绪的,而检测就是在访问临界资源!所以要加锁之后才能wait
        pthread_mutex_lock(pmtx);
        //条件变量检测临界资源
        //if("资源是否就绪")
        //不就绪
        pthread_cond_wait(pcond,pmtx);//默认该线程在执行的时候,wait代码被执行,当前线程会立即被阻塞
        //

        
        cout << name << "播放" << endl;
        pthread_mutex_unlock(pmtx);

    }
}

void func2(const string &name,pthread_mutex_t *pmtx,pthread_cond_t *pcond)
{
   while(!quit)
    {
        pthread_mutex_lock(pmtx);

        pthread_cond_wait(pcond,pmtx);//默认该线程在执行的时候,wait代码被执行,当前线程会立即被阻塞

        cout << name << "下载" << endl;
        pthread_mutex_unlock(pmtx);

    }
}

void func3(const string &name,pthread_mutex_t *pmtx,pthread_cond_t *pcond)
{
   while(!quit)
    {
        pthread_mutex_lock(pmtx);

        pthread_cond_wait(pcond,pmtx);//默认该线程在执行的时候,wait代码被执行,当前线程会立即被阻塞
        cout << name << "刷新" << endl;
        pthread_mutex_unlock(pmtx);

    }
}

void func4(const string &name,pthread_mutex_t *pmtx,pthread_cond_t *pcond)
{
   while(!quit)
    {
        pthread_mutex_lock(pmtx);

        pthread_cond_wait(pcond,pmtx);//默认该线程在执行的时候,wait代码被执行,当前线程会立即被阻塞
        cout << name << "扫描信息" << endl;
        pthread_mutex_unlock(pmtx);

    }
}

void *Entry(void *args)
{
    ThreadDate *td=(ThreadDate*)args;
    td->func_(td->name_,td->pmtx_,td->pcond_);
    delete td;
    return nullptr;

}

int main()
{
    pthread_mutex_t mtx;
    pthread_cond_t cond;
    pthread_mutex_init(&mtx,nullptr);
    pthread_cond_init(&cond,nullptr);

    pthread_t tids[TNUM];
    func_t funcs[TNUM]={func1,func2,func3,func4};

    //创建线程
    for(int i = 0;i<TNUM;i++)
    {
        string name="Thread ";
        name+=to_string(i+1);
        ThreadDate *td=new ThreadDate(name,funcs[i],&mtx,&cond);
        pthread_create(tids+i,nullptr,Entry,(void*)td);
    }

    sleep(2);


    //控制线程,尝试唤醒等待的线程
    int con = 3;
    while(con)
    {
        cout<<"唤醒线程  "<<"唤醒次数: "<<con--<<endl;
        //pthread_cond_signal(&cond);//一个一个唤醒
        pthread_cond_broadcast(&cond);//一次性唤醒所有
        sleep(1);
    }
    cout<<"ctrl done"<<endl;
    quit=true;
    pthread_cond_broadcast(&cond);//让所有的新线程在执行一次,进行下检测

    //等待线程
    for(int i =0;i<TNUM;i++)
    {
        pthread_join(tids[i],nullptr);
        cout<<"Thread   "<<tids[i]<<"quit"<<endl;
    }

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

在没有条件变量的时候,新线程会排队等待,我们的主线程在排队唤醒新线程,这样我们就可以让我们的线程在收到信号之后完成不同的问题

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

中型企业运维总监的成本优化实战案例——自建IDC机房

早期互联网快速发展的时候&#xff0c;相关领域的公司更注重拓展业务。 为了快速占领市场&#xff0c;他们往往投入了较高的成本。 但近年来&#xff0c;随着互联网人口红利的逐渐消退以及疫情的影响&#xff0c;越来越多的企业开始重视成本管理&#xff0c;从“粗放式经营”向…

使用J-Link Commander通过J-LINK以命令的形式来访问ARM通用MCU

通常我们的操作是写好程序然后将程序下载到芯片里面&#xff0c;然后运行程序来进行相应的操作&#xff0c;其实还可以使用 J − L i n k C o m m a n d e r J-Link\quad Commander J−LinkCommander通过 J − L I N K J-LINK J−LINK以命令的形式来简单访问ARM通用MCU&#xf…

Hadoop运行搭建——系统配置和Hadoop的安装

Hadoop运行搭建 前言&#xff1a; 本文原文发在我自己的博客小站&#xff0c;直接复制文本过来&#xff0c;所以图片不显示(我还是太懒啦&#xff01;)想看带图版的请移步我的博客小站~ Linux镜像&#xff1a;CentOS7 系统安装&#xff1a;CentOS安装参考教程 系统网卡设置…

微信私信短剧机器人源码

本源码仅提供参考&#xff0c;有能力的继续开发 接口为api调用 云端同步 https://ys.110t.cn/api/ajax.php?actyingshilist 影视搜索 https://ys.110t.cn/api/ajax.php?actsearch&name剧名 每日更新 https://ys.110t.cn/api/ajax.php?actDaily 反馈接口 https://ys.11…

SpringCloud-Alibaba-Nacos教程

SpringCloud-Alibaba-Nacos教程 下载地址 https://github.com/alibaba/nacos/releases/tag/2.2.3 直接进入bin包 运行cmd命令 startup.cmd -m standalone 运行成功后 进入nacos可视化页面 账号密码默认都是nacos http://localhost:8848/nacos 微服务入驻Nacos服务注册…

从 iPhone 设备恢复误删微信消息的 4 种方法

您的微信消息可能会因无意删除、系统崩溃、卸载微信应用或升级过程失败而被删除。如果您遇到这种情况&#xff0c;您不必担心&#xff0c;因为您可以采取某些步骤来恢复丢失的微信历史记录。这里有 4 种方法可以帮助您从 iPhone恢复丢失的微信消息、群聊历史记录或微信联系人。…

JMH287亲测【鸣潮】一键内测风景端V1.0.2已整理并录制视频教学

资源介绍&#xff1a; 否需要虚拟机&#xff1a;否 文件大小&#xff1a;压缩包约15G 支持系统&#xff1a;win7、win10、win11 硬件需求&#xff1a;运行内存16G 4核及以上CPU独立显卡 资源截图&#xff1a; 下载地址&#xff1a; JMH287【鸣潮】一键端 [V1.0.2]

算法学习08:Trie树(字典树)、并查集

算法学习08&#xff1a;Trie树&#xff08;字典树&#xff09;、并查集 文章目录 算法学习08&#xff1a;Trie树&#xff08;字典树&#xff09;、并查集前言一、Trie树&#xff08;字典树&#xff09;二、并查集1.例题1&#xff1a;合并 判断2.例题2&#xff1a;合并 判断 …

ChatGPT发不出消息?GPT发不出消息怎么办?

前言 今天发现&#xff0c;很多人的ChatGPT无法发送信息&#xff0c;我就登陆看一下自己的GPT的情况&#xff0c;结果还真的无法发送消息&#xff0c;ChatGPT 无法发送消息&#xff0c;但是能查看历史的对话&#xff0c;不过通过下面的方法解决了。 第一时间先打开官方的网站&a…

STM32---通用定时器(一)理论基础

写在前面&#xff1a;在STM32F103中有众多的定时器&#xff0c;其中包括两个基本定时器&#xff0c;基本定时器的内容已经在上节进行了介绍&#xff0c;基本定时器的功能、结构、使用都较为简单。而STM32F1中还含有4个通用定时器&#xff08;TIM2\3\4\5&#xff09;,这些定时器…

Unity零基础到进阶 | Unity中 屏蔽指定UI点击事件 的多种方法整理

Unity零基础到进阶 | Unity中 屏蔽指定UI点击事件 的多种方法整理一、Unity中 屏蔽透明区域的点击事件1.1 使用Image组件自带的参数检测1.2 根据点击的坐标计算该点的像素值是否满足阈值 二、Unity中屏蔽 不规则图片按钮点击的事件 总结 &#x1f3ac; 博客主页&#xff1a;htt…

剑指offer经典题目整理(二)

一、斐波那契数列&#xff08;fib&#xff09; 1.链接 斐波那契数列_牛客题霸_牛客网 (nowcoder.com) 2.描述 斐波那契数列就是数列中任意一项数字&#xff0c;都会等于前两项之和&#xff0c;满足f(n) f(n-1) f(n-2) 的一个数列&#xff0c;例如&#xff1a;1 1 2 3 5 8…

JVM知识整体学习

前言&#xff1a;本篇没有任何建设性的想法&#xff0c;只是我很早之前在学JVM时记录的笔记&#xff0c;只是想从个人网站迁移过来。文章其实就是对《深入理解JVM虚拟机》的提炼&#xff0c;纯基础知识&#xff0c;网上一搜一大堆。 一、知识点脑图 本文只谈论HotSpots虚拟机。…

2024年腾讯云8核16G服务器性能测试和并发数测试

腾讯云8核16G轻量服务器CPU性能如何&#xff1f;18M带宽支持多少人在线&#xff1f;轻量应用服务器具有100%CPU性能&#xff0c;18M带宽下载速度2304KB/秒&#xff0c;折合2.25M/s&#xff0c;系统盘为270GB SSD盘&#xff0c;月流量3500GB&#xff0c;折合每天116.6GB流量&…

开源的Java图片处理库介绍

在 Java 生态系统中&#xff0c;有几个流行的开源库可以用于图片处理。这些库提供了丰富的功能&#xff0c;如图像缩放、裁剪、颜色调整、格式转换等。以下是几个常用的 Java 图片处理库的介绍&#xff0c;包括它们的核心类、主要作用和应用场景&#xff0c;以及一些简单的例子…

spring-cloud-openfeign 3.0.0之前版本(对应spring boot 2.4.x之前版本)feign配置加载顺序

在之前写的文章配置基础上 https://blog.csdn.net/zlpzlpzyd/article/details/136060312 下图为自己整理的

Linux:kubernetes(k8s)prestop事件的使用(10)

他的作用是在结束pod容器之后进行的操作 apiVersion: v1 # api文档版本 kind: Pod # 资源对象类型 metadata: # pod相关的元数据&#xff0c;用于描述pod的数据name: nginx-po # pod名称labels: # pod的标签type: app #这个是随便写的 自定义的标签version: 1.0.0 #这个…

借助 Terraform 功能协调部署 CI/CD 流水线-Part 1

在当今快节奏的开发环境中&#xff0c;实现无缝、稳健的 CI/CD 流水线对于交付高质量软件至关重要。在本文中&#xff0c;我们将向您介绍使用 Bitbucket Pipeline、ArgoCD GitOps 和 AWS EKS 设置部署的步骤&#xff0c;所有步骤都将利用 Terraform 的强大功能进行编排。在Part…

Linux 之二:CentOS7 的 IP 常用命令和配置及 xshell 基本使用方法

1. 进入虚拟机 点击右键---进入终端--输入 ip adrr 或 ifconfig 查看ip地址 下面输入命令 ifconfig&#xff08;注意&#xff1a;不是 ipconfig &#xff09; 或 ip addr 来查看当前系统 IP 查看到IP 后&#xff0c;比如&#xff1a;上面是 192.168.184.137 1.1 IP 常用命令…

[VulnHub靶机渗透] Nullbyte

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收…