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,这是因为我们需要检测临界资源是否就绪的,而检测就是在访问临界资源!所以要加锁之后才能waitpthread_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;
}

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

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

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

相关文章

超网、IP 聚合、IP 汇总分别是什么?三者有啥区别和联系?

一、超网 超网&#xff08;Supernet&#xff09;是一种网络地址聚合技术&#xff0c;它可以将多个连续的网络地址合并成一个更大的网络地址&#xff0c;从而减少路由表的数量和大小。超网技术可以将多个相邻的网络地址归并成一个更大的网络地址&#xff0c;这个更大的网络地址…

群辉docker安装sql server

安装步骤 开启群辉 SSH&#xff0c;通过 SSH 工具连接到群辉&#xff0c;运行下面的命令拉取mssql 2019 镜像 sudo docker pull mcr.microsoft.com/mssql/server:2019-latest然后在 docker 中就可以看到该镜像&#xff1a; 在群晖 docker 共享文件夹中创建 mssql2009 文件夹 …

了解 HTTPS 中间人攻击:保护你的网络安全

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

C#,数值计算,解微分方程的龙格-库塔二阶方法与源代码

1 微分方程 含有导数或微分的方程称为微分方程&#xff0c;未知函数为一元函数的微分方程称为常微分方程。 微分方程的阶数 微分方程中导数或微分的最高阶数称为微分方程的阶数。 微分方程的解 使得微分方程成立的函数称为微分方程的解。 微分方程的特解 微分方程的不含任意…

Linux之生产消费者模型

(&#xff61;&#xff65;∀&#xff65;)&#xff89;&#xff9e;嗨&#xff01;你好这里是ky233的主页&#xff1a;这里是ky233的主页&#xff0c;欢迎光临~https://blog.csdn.net/ky233?typeblog 点个关注不迷路⌯▾⌯ 我们在条件满足的时候&#xff0c;唤醒指定的线程&a…

深入理解 Webpack 热更新原理:提升开发效率的关键

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

从零开始:神经网络(1)——神经元和梯度下降

声明&#xff1a;本文章是根据网上资料&#xff0c;加上自己整理和理解而成&#xff0c;仅为记录自己学习的点点滴滴。可能有错误&#xff0c;欢迎大家指正。 一. 神经网络 1. 神经网络的发展 先了解一下神经网络发展的历程。从单层神经网络&#xff08;感知器&#xff09;开…

selenium元素定位问题

具体网页信息如下&#xff1a; 定位的时候driver.find_element(By.CLASS_NAME, 方法搞不定。 定位方法&#xff1a; 方法一&#xff1a;通过文本定位 driver.find_element(By.XPATH, "//*[text()高分一号]").click() time.sleep(3) 如果是部分文字 #部分文字py…

安卓提示风险解决源码搭建教程

一&#xff0e;环境 1.安装Nginx 2.安装Tomcat8.5 3. 安装Mysql5.7 二&#xff0e;修改app已生成的文件下载地址 1.打开编辑config.properties 2.填写你的ip&#xff0c;端口不用修改 三&#xff0e;启动教程 启动命令&#xff1a;sh.start.sh 源码下载链接:https://p…

贪心算法(蓝桥杯 C++ 题目 代表 注解)

介绍&#xff1a; 贪心算法&#xff08;Greedy Algorithm&#xff09;是一种在每一步选择中都采取当前状态下最好或最优&#xff08;即最有利&#xff09;的选择&#xff0c;从而希望最终能够得到全局最好或最优的结果的算法。它通常用来解决一些最优化问题&#xff0c;如最小生…

JVM基本概念、命令、参数、GC日志总结

原文: 赵侠客 一、前言 NPE&#xff08;NullPointerException&#xff09;和OOM&#xff08;OutofMemoryError&#xff09;在JAVA程序员中扮演着重要的角色&#xff0c;它也是很多人始终摆脱不掉的梦魇&#xff0c;与NPE不同的是OOM一旦在生产环境中出现就意味着只靠代码已经无…

FPGA的配置状态字寄存器Status Register

目录 简介 状态字定义 Unknown Device/Many Unknow Devices 解决办法 一般原因 简介 Xilinx的FPGA有多种配置接口&#xff0c;如SPI&#xff0c;BPI&#xff0c;SeletMAP&#xff0c;Serial&#xff0c;JTAG等&#xff1b;如果从时钟发送者的角度分&#xff0c;还可以…