网络编程day6——基于C/S架构封装的线程池

一、线程竞争基本概念

    竞争与同步

        同一个进程中的线程共享进程中的绝大多数资源,当它们随意竞争时可能会导致资源被破坏、脏数据、不完整问题

        通过一些手段让线程在竞争资源时相互协调、避免出现以上问题,这就称为线程同步

    原子操作:

        操作过程中不能被打断的操作称为原子操作

    临界资源、临界区、竞态条件:

        能够被多个进程访问但是又无法同时访问的资源称为临界资源

        每个进程中访问临界资源的那段代码称为临界区,能够被多个线程访问但是又无法同时访问的代码片段

        多个线程在临界区内执行时,由于线程的执行顺序具有随机性,从而导致结果不确定,称为发生了竞态条件

二、互斥量(互斥锁)

    man手册中没有全部的posix手册文档,需要安装

    sudo apt-get install manpages-posix-dev

    pthread_mutex_t 是一种数据类型,用来定义互斥锁变

    int pthread_mutex_init(pthread_mutex_t* mutex,const pthread_mutexattr_t * attr);

    功能:对互斥量进行初始化,完成后锁处于开锁状态

    mutex:要初始化的互斥量

    attr:互斥量的属性设置,一般默认给NULL即可

   

    也可以在定义时通过PTHREAD_MUTEX_INITIALIZER初始化互斥量

    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

    int pthread_mutex_lock(pthread_mutex_t *mutex);

    功能:对互斥量加锁,成功则返回继续执行,失败则阻塞休眠等待,直到互斥量解锁并成功加锁才唤醒返回

    int pthread_mutex_unlock(pthread_mutex_t *mutex);

    功能:对互斥量解锁,对别人上锁的互斥量解锁,失败返回EBUSY

    int pthread_mutex_trylock(pthread_mutex_t *mutex);

    功能:对互斥量尝试加锁,成功返回0 失败返回EBUSY,立即返回

    int pthread_mutex_destroy(pthread_mutex_t *mutex);

    功能:销毁互斥量

三、读写锁

    读写锁将线程访问共享数据时发出的请求分为两种:

        读请求:只读取共享数据,不修改

        写请求:存在修改共享数据的行为

        1、当有多个线程同时发出读请求,可以同时执行

        2、当有多个线程同时发出写请求,只能一个一个的执行

        3、当发出读请求的线程正在执行时,发出写请求的线程必须等待前面所有读请求线程执行完后才能执行

        4、当发出写请求的线程正在执行时,发出读请求的线程必须等待前面所有写请求线程执行完后才能执行

    当读写锁被发出读请求的线程占用时,称为"读锁",当读写锁被发出读请求的线程占用时,称为"写锁"

        1、当读写锁未被任何线程占用,称为"无锁",发出读请求、写请求的线程都可以占用,如果同时请求,默认优先给读请求占用

        2、当变成读锁(多个线程占用)时,读请求的线程可以占用不会阻塞,但是写请求的线程会阻塞等待读锁解锁

        3、当变成写锁(单个线程占用)时,读、写请求的线程都会阻塞等待写锁解锁

        pthread_rwlock_init 初始化读写锁

        pthread_rwlock_wrlock 写锁上锁

        pthread_rwlock_rdlock 读锁上锁

        pthread_rwlock_unlock 解锁

        pthread_rwlock_destroy 销毁

   

四、自旋锁

    在任意时刻最多只能有一个线程获取该锁

    对于互斥量,如果资源已经被占用,申请者会进入休眠态

    对于自旋锁,则不会引起申请者休眠,而是一直在申请处进入循环不停地查看自旋锁是否解锁,直到解锁并加锁成功后才退出循环往下执行

    一般情况下使用互斥量,但是如果知道被锁住的代码执行时间很短(或者是主动让其变短),那么应该选择使用系统开销(运行态<->休眠态)较少的自旋锁更合适,因为运行态进入休眠态时,需要切换内核态 有点耗时

五、信号量

    与进程间通信XSI机制中的信号量原理相似,线程之间使用的"全局"的计数器,用于控制访问有限的共享数据的线程数

    sem_t 是一种数据类型,用于定义信号量变量

    int sem_init(sem_t *sem, int pshared, unsigned int value);

    功能:初始化信号量

    sem:要初始化的信号量

    pshared:

        0   只能在本进程中使用

        非0 表示该信号量可以以共享内存的方式被多个进程使用,Linux不支持

    value:信号量的初始值

    int sem_wait(sem_t *sem);

    功能:对信号量减1,如果信号量的值为0,则阻塞等待

    int sem_trywait(sem_t *sem);

    功能:对信号量尝试减1,如果信号量的值为0,则立即返回EAGAIN,成功返回0

    int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

    功能:对信号量减1,如果值为0,则等待一段时间,超时还没能减则返回ETIMEDOUT

    int sem_post(sem_t *sem);

    功能:对信号量的值加1

    int sem_destroy(sem_t *sem);

    功能:销毁信号量

六、死锁

    1、什么是死锁

        多个进程或线程相互等待对方的资源,在得到新资源前不会释放自己的旧资源,这样就形成了循环等待,该现象称为死锁

    2、产生死锁的四大必要条件

        资源互斥:资源只有两种状态,可用和不可用,资源不能被同时使用,同一时刻只能被一个进程或线程使用

        占用且请求:已经得到资源的进程或线程,会继续请求新的资源,并且持续占用旧资源

        资源不可剥夺:当资源已经分配给进程或线程后,不能被其他进程或线程强制性获取,除非占用者主动释放

        环路等待:死锁发生时,系统中必定有两个或以上的进程或线程的执行路线形成等待环路

        注意:一旦产生死锁基本无解,现在的操作系统无法解决死锁,因此只能防止死锁的产生

    3、防止死锁产生的方法

        破坏互斥条件:

            想办法让资源能够共享

            缺点:受到环境或资金的影响无法让资源共享

        破坏占用且请求:

            采用静态预分配的方式,进程或线程在运行前尝试一次性申请所有的资源,在资源没有得到全部满足不投入运行

            缺点:可能会导致系统资源的昂费,因为有些资源是很靠后才会使用,但是已经提前分配占用,导致其它不会产生死锁的进程或线程也无法使用

        破坏资源不可剥夺:

            当一个进程或线程占用了不可被剥夺的资源,并且请求新资源无法得到满足时,那么就把全部占用的资源主动释放,过一段时间后重新开始

            缺点:该策略实现难度高,释放已经占用的资源会导致前一阶段的工作失效,还要反复申请释放资源,浪费资源、时间

        破坏环路等待:

            给每个资源进行编号,进程或线程都按照编号顺序来请求资源,并且必须拿到前一个编号资源后,才能去拿后一个

            缺点:资源的编号顺序要相对稳定,否则在运行期间资源的增加或删减都会让该过程受极大的影响

    4、如何判断死锁

        1、画出资源分配图

        2、简化资源分配图

        3、使用死锁定理判断:看有没有环路

七、条件变量

    当某些设置的条件满足时可以让线程自己进入睡眠态,也可以在另一些设置的条件满足时可以被其它线程唤醒,需要配合互斥量使用

    pthread_cond_t 是一种数据类型,用于定义条件变量

    int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);

    功能:初始化条件变量,也可以直接使用PTHREAD_COND_INITIALIZER在定义时初始化

    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

    int pthread_cond_destroy(pthread_cond_t *cond);

    功能:销毁条件变量

    int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);

    功能:让当前线程睡入条件变量cond,并主动解锁线程自己的互斥量mutex  //拿到资源先上锁,满足条件就睡眠,并且解锁

    int pthread_cond_signal(pthread_cond_t *cond);

    功能:唤醒因为cond睡眠的其中一个线程,线程醒来前要确保能对原来的互斥量重新加锁  //醒来之后 要能够拿到资源并上锁 与睡眠前的状态保持一致

    int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct timespec *restrict abstime);

    功能:让当前线程睡入cond,最多睡abstime时间,超时也会返回

    使用条件变量和互斥量可以实现 生产者和消费者模型

八、生产者与消费者模型 (C/S模型)

    生产者:生产数据的线程

    消费者:使用数据的线程

    仓库:临时存储数据的缓冲区(仓库解决生产、消费不匹配的问题)

    可能产生的问题:

        生产快于消费:仓库爆满,撑死

        消费快于生产:仓库空虚,饿死

    利用条件变量来解决以上问题:

        当缓冲区满的时候,生产者睡入条件变量(full),并通知消费者全部醒了(empty)

        当缓冲区空的时候,消费者睡入条件变量(empty),并通知生产者全部醒来(full)

应用:利用生产者消费者模型构建 线程池

线程池的封装(gitee)

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

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

相关文章

第16节-PhotoShop基础课程-修复工具组-去水印

文章目录 前言1.污点修复画笔1.功能原理2.调整1.调整大小 Alt 右键 左右2.调整软硬 Alt 右键 上下 2.修复画笔工具 Alt 选取源1.常规2.选择图案 3.修补工具1.类型1.源2.目标 2.扩展 4.内容感知移动工具5.红眼工具 前言 去水印等 1.污点修复画笔 比如把下面的土豆&#xff08…

Scrum敏捷模式的优势点、实践经验及适用企业

Scrum敏捷模式是一种灵活、适应性强的开发方法&#xff0c;其核心理念是以短周期、高频率的方式进行项目开发&#xff0c;确保团队能够快速响应变化。 Scrum包含三个角色&#xff1a;产品负责人&#xff08;Product Owner&#xff09;、Scrum Master和开发团队&#xff08;Tea…

【程序员装机】Windows常见问题解决指南

文章目录 前言从专业版升级到企业版禁用Y空间的录制IDM扩展失效Edge浏览器安装CRX扩展 总结 前言 本文将介绍如何将Windows操作系统中的专业版升级为企业版&#xff0c;以及一些与系统和应用程序相关的常见问题的解决方法。 从专业版升级到企业版 如果您希望将专业版的Window…

【交叉熵损失torch.nn.CrossEntropyLoss详解-附代码实现】

CrossEntropyLoss 什么是交叉熵softmax损失计算验证CrossEntropyLoss 输入输出介绍验证代码 什么是交叉熵 交叉熵有很多文章介绍&#xff0c;此处不赘述。只需要知道它是可以衡量真实值和预测值之间的差距的&#xff0c;因而用交叉熵来计算损失的时候&#xff0c;损失是越小越…

详解TCP/IP协议第一篇:网络基础知识

文章目录 写给自己的话 一:前言 1:手握金刚钻的TCP/IP 2:计算机中的协议 3:分组

深入了解HTTP代理的工作原理

HTTP代理是一种常见的网络代理方式&#xff0c;它可以帮助用户隐藏自己的IP地址&#xff0c;保护个人隐私和安全。了解HTTP代理的工作原理对于使用HTTP代理的用户来说非常重要。本文将深入介绍HTTP代理的工作原理。 代理服务器的作用 HTTP代理的工作原理基于代理服务器的作用。…

Android常用的工具“小插件”——Widget机制

Widget俗称“小插件”&#xff0c;是Android系统中一个很常用的工具。比如我们可以在Launcher中添加一个音乐播放器的Widget。 在Launcher上可以添加插件&#xff0c;那么是不是说只有Launcher才具备这个功能呢&#xff1f; Android系统并没有具体规定谁才能充当“Widget容器…

2023年“羊城杯”网络安全大赛 Web方向题解wp 全

团队名称&#xff1a;ZhangSan 序号&#xff1a;11 不得不说今年本科组打的是真激烈&#xff0c;初出茅庐的小后生没见过这场面QAQ~ D0n’t pl4y g4m3!!! 简单记录一下&#xff0c;实际做题踩坑很多&#xff0c;尝试很多。 先扫了个目录&#xff0c;扫出start.sh 内容如下…

Linux CentOS7 系统中添加用户

在linux centOS7系统中&#xff0c;添加用户是管理员的基本操作。作为学习linux系统的基本操作&#xff0c;对添加用户应该多方面了解。 添加用户的命令useradd&#xff0c;跟上用户名&#xff0c;就可以快速创建一个用户。添加一些选项&#xff0c;可以设置更人性化的用户信息…

【论文阅读】Pay Attention to MLPs

作者&#xff1a;Google Research, Brain Team 泛读&#xff1a;只关注其中cv的论述 提出了一个简单的网络架构&#xff0c;gMLP&#xff0c;基于门控的MLPs&#xff0c;并表明它可以像Transformers一样在关键语言和视觉应用中发挥作用 提出了一个基于MLP的没有self-attentio…

docker 笔记11: Docker容器监控之CAdvisor+InfluxDB+Granfana

1.原生命令 docker stats命令的结果 是什么 2.是什么 容器监控3剑客 CAdvisor监控收集InfluxDB存储数据Granfana展示图表 3.CAdvisor 4.InfluxDB 5.Granfana 6.总结 7.compose容器编排&#xff0c;一套带走 新建目录 7.1新建3件套组合的 docker-compose.yml version: 3.1vo…

网络原理

网络原理 传输层 UDP 特点 特点&#xff1a;无连接&#xff0c;不可靠&#xff0c;面向数据报&#xff0c;全双工 格式 怎么进行校验呢&#xff1f; 把UDP数据报中的源端口&#xff0c;目的端口&#xff0c;UDP报文长度的每个字节&#xff0c;都依次进行累加 把累加结果&a…

人脸识别技术,如何解决学校门禁安全?

在当今社会&#xff0c;学校安全已经成为一个备受关注的议题&#xff0c;而门禁监控系统已经成为学校管理和保障学生安全的重要工具之一。随着社会的不断发展和技术的不断进步&#xff0c;学校不再只是知识传授的场所&#xff0c;它们也成为了数百、数千甚至数万学生和教职员工…

Elasticsearch——Docker单机部署安装

文章目录 1 简介2 Docker安装与配置2.1 安装Docker2.2 配置Docker镜像加速器2.3 调整Docker资源限制 3 准备Elasticsearch Docker镜像3.1 下载Elasticsearch镜像3.2 自定义镜像配置3.3执行Docker Compose 4 运行Elasticsearch容器4.1 创建Elasticsearch容器4.2 修改配置文件4.3…

入门人工智能 —— 使用 Python 进行文件读写,并完成日志记录功能(4)

入门人工智能 —— 使用 Python 进行文件读写&#xff08;4&#xff09; 入门人工智能 —— 使用 Python 进行文件读写打开文件读取文件内容读取整个文件逐行读取文件内容读取所有行并存储为列表 写入文件内容关闭文件 日志记录功能核心代码&#xff1a;完整代码&#xff1a;运…

题目:2677.分块数组

​​题目来源&#xff1a; leetcode题目&#xff0c;网址&#xff1a;2677. 分块数组 - 力扣&#xff08;LeetCode&#xff09; 解题思路&#xff1a; 按要求分块即可。 解题代码&#xff1a; /*** param {Array} arr* param {number} size* return {Array[]}*/ var chunk …

day28 代码回想录 复原IP地址子集子集II

大纲 ● 93.复原IP地址 ● 78.子集 ● 90.子集II 93.复原IP地址 题目&#xff1a;93.复原IP地址 复原ip地址&#xff0c;需要将字符串进行分隔&#xff0c;特别小心处理ip格式的判断 本题也是字符分割的题目&#xff0c;确定分割的点&#xff0c;作为递归参数传入 vector&l…

UE5、CesiumForUnreal实现瓦片坐标信息图层效果

文章目录 1.实现目标2.实现过程2.1 原理简介2.2 cesium-native改造2.3 CesiumForUnreal改造2.4 运行测试3.参考资料1.实现目标 参考CesiumJs的TileCoordinatesImageryProvider,在CesiumForUnreal中也实现瓦片坐标信息图层的效果,便于后面在调试地形和影像瓦片的加载调度等过…

超详细最新PyCharm+Python环境安装,多图,逐步骤

PyCharmPython环境安装 前言一、pycharm下载安装1. 安装地址2. 安装详细步骤 二、Python下载安装1. 安装地址2. 安装详细步骤3. 环境变量忘记添加4. python安装成功测试 三. PyCharm上配置Python总结推荐文章 前言 文章会详细介绍PyCharmPython详细安装步骤&#xff0c;接下来…

vim的使用快捷键之删除、复制、粘贴

x 小写的x表示向后删除一个字符,也就是删除光标所在字符 nx n表示数字&#xff0c;表示向后删除每个字符&#xff0c;例如&#xff1a;10x表示删除包括光标在内的后面10个字符 X 大写的X表示删除光标前的一个字符,不包括光标所在字符 nX n表示数字&#xff0c;表示向前删除每…