线程的创建与同步

news2025/1/10 1:21:41

线程的创建与同步

  • 线程的概念与实现方式
    • 线程的概念
    • 进程线程的区别
  • 线程使用
    • 线程相关的接口函数
    • 多线程代码
    • 线程并发
  • 线程的实现方式
  • 线程的同步
    • 信号量
    • 互斥锁
    • 读写锁
    • 条件变量
  • 线程的安全
  • 线程与fork

线程的概念与实现方式

线程的概念

进程是正在执行的程序。线程是进程内部的一条执行路径,一个进程可以有多个线程。在这里插入图片描述

进程线程的区别

  • 进程是资源分配的最小单位,线程是CPU调度的最小单位。
  • 进程有自己的独立地址空间,线程共享进程中的地址空间。
  • 进程的创建消耗资源大,线程的创建相对较小。
  • 进程的切换开销大,线程的切换开销相对较小。

线程使用

线程相关的接口函数

int pthread_create(pthread_t* thread,const pthread_attr_t* attr,void* (start_routine)(void),void arg);
用于创建线程,thread:接收线程ID。attr:线程属性。start_rountine:指定线程函数。arg:线程函数传递的参数。

int pthread_exit(void *retval);
退出线程,retval:指定退出程序。

int pthread_join(pthread_t thread, void **retval);
等待thread指定的线程退出,线程未退出时,该方法阻塞。retval:接收thread线程退出时,指定的退出信息。

多线程代码

实例1:
在这里插入图片描述
运行结果:在这里插入图片描述

线程并发

在这里插入图片描述
运行结果:在这里插入图片描述
以上程序我们有五个线程,每个线程打印三次,将主程序中的i的地址传递给我们的线程,线程获取i的值将其打印。我们将三次打印的值分别分开如下图:在这里插入图片描述
我们发现三次打印的值都一样,只是顺序不一样,是因为线程运行速度不一样所以输出的顺序才会发生改变。此处要注意:例如线程5,我们将i的地址赋值给线程5时,此时i为4,但是当线程获取i的值时,i已经进入了我们第二次获取退出信息的循环,此时i=0,所以线程5才会输出0。
示例二:
在这里插入图片描述
求最后一次输出结果。
我们肯定会想到有五个进程,每个进程对count进行后置++,所以最后一次输出肯定是5000,输出结果呢大部分情况下也是5000,但是会有一部分情况下会小于5000,是为什么呢?
多个线程抢占一个cpu,就会进行并发处理,但是如果有多个处理器,就会发生一个处理器处理一个线程,导致并行处理,这样会使得两个线程同时加一,就会少一次自增。

线程的实现方式

线程的实现方式从操作系统的角度分为:用户级,内核级,组合
用户级:开销小,可以创建很多,但不能利用多处理器资源。
内核级:开销大,由内核直接管理,可以利用多处理器资源。
linux操作系统实现方式:内核级,linux比较特殊,没有特定的线程,以进程的方式实现,每个线程都有相对应的struct task_struct;PCB。

线程的同步

线程的同步指的是一个线程在对某个资源进行操作时,其他线程都不可以对这个资源进行操作,直到该线程完成操作,其他线程才可以操作,也就是协同步调,让线程按预定的先后顺序进行运行。线程同步的方法有四种:信号量,互斥锁,条件变量,读写锁

信号量

信号量特殊的资源总量,p操作获取资源-1,v操作释放资源+1。临界资源:同一时刻只允许一个进程访问的资源。临界区:访问临界资源的代码段。
头文件:#include<semaphore.h>
int sem_init(sem_t* sem,int psshared,unsigned int value);//初始化函数
int sem_wait(sem_t* sem);//p操作
int sem_post(sem_t* sem);//v操作
int sem_destroy(sem_t *sem);//销毁信号量
代码演示:
创建三个线程,让其有序输出ABCABC……
代码:
在这里插入图片描述
在这里插入图片描述
运行结果:在这里插入图片描述

互斥锁

互斥锁中有加锁和解锁操作。
pthread_mutex_init();//初始化
pthread_mutex_destroy();//销毁
pthread_mutex_lock();//加锁
pthread_mutex_unlock();//解锁
代码举例:
我们上面有一个例题,五个线程,每个线程对一个全局变量进行+1操作执行1000次,我们会发现当内核cpu大于等于2时会出现总数小于5000的情况,因为同时对同一个值进行+1操作,就等于自增一次。我们可以通过互斥锁使得这种情况进行阻塞。
在这里插入图片描述
运行结果:每一次最终相加结果为5000.在这里插入图片描述

读写锁

读写锁就和名字一样存在读和写两种操作,不同之处在于可以同时读,但是写的时候不能读,也不能写,也就是说我们进行读操作时可以进行另外的读操作,但不能进行写操作。
pthread_rwlock_rdlock//读操作
pthread_rwlock_wrlock//写操作
pthread_rwlock_unlock//解锁
pthread_rwlock_init//初始化
pthread_rwlock_destroy//删除锁
代码举例:
创建三个线程,两个进行写操作,一个进行读操作。
在这里插入图片描述
在这里插入图片描述
执行结果:在这里插入图片描述

通过运行结果我们可以发现两次读操作可以同时运行,但是写操作只能独自运行。

条件变量

条件变量提供了一种线程间的通知机制:当某个共享数据达到某个值的时候,唤醒等待这个共享数据的线程。在这里插入图片描述
int pthread_cond_init//初始化
int pthread_cond_wait//等待
int pthread_cond_signal//唤醒单个线程
int pthread_cond_broadcast//唤醒所有等待的线程
int pthread_cond_destroy//销毁消息变量
代码演示:
在这里插入图片描述
在这里插入图片描述

运行结果:在这里插入图片描述

线程的安全

线程安全就是在多线程运行的过程中,不管线程的调度顺序怎么样,最终结果都是安全的。
保证线程安全两点要素:

  • 对线程同步,保证同一时刻只有一个线程访问临界资源。
  • 在多线程中使用线程安全的函数。(线程安全函数:一个函数能被多个线程同时调用且巴布达省静态条件)

线程同步我们上面已经详细讲述,我们可以通过举例了解一下线程安全函数。
在这里插入图片描述
观察上面的代码,我们期待的运行结果应改时输出a1b2c3d4e…但是我们运行之后会发现结果不尽人意:
在这里插入图片描述
因为strtok函数中存在一个静态变量,导致运行两个strtok函数出现冲突。
修改后代码如下:在这里插入图片描述
运行结果如下:

在这里插入图片描述

线程与fork

fork函数在哪一个线程上仅分裂当前线程。
将线程安全代码线程中加入fork函数,
在这里插入图片描述
运行结果如下:在这里插入图片描述
我们会发现仅对当前线程进行了分裂。

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

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

相关文章

MXNet的Faster R-CNN(基于区域提议网络的实时目标检测)《4》

这篇主要了解语义分割(semantic segmentation)&#xff0c;语义分割是分类中的一个核心知识点&#xff0c;而且这些语义区域的标注和预测都是像素级的。在语义分割中有两个很相似的重要问题&#xff0c;需要注意下&#xff1a;图像分割(image segmentation)&#xff1a;将图像分…

一文解决用C语言实现一个链表(全都是细节)

目录前言单链表1.链表中的结点2.链表中的常见操作&#xff08;1&#xff09;相关声明格式&#xff08;2&#xff09;常见操作的实现&#xff08;定义&#xff09;&#xff08;5&#xff09;测试前言 链表是指数据使用一个一个的结点连接起来的数据结构&#xff0c;这样的数据结…

(框架)Deepracer Local - 001: 搭建本地环境

Deepracer - 阿里云1. 安装环境2. 预安装脚本3. 从 github 下载 deepracer 代码 并初始化4. 首次运行deepracer1. 安装环境 推荐本地环境: Ubuntu (如果windowns必要的话&#xff0c;就装双系统&#xff0c;我的台式机就是双系统) 云环境: 阿里云&#xff0c;配置如下&#xf…

python简单介绍及基础知识(二)

♥️作者&#xff1a;小刘在这里 ♥️每天分享云计算网络运维课堂笔记&#xff0c;疫情之下&#xff0c;你我素未谋面&#xff0c;但你一定要平平安安&#xff0c;一 起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的&#xff0c;绽放&#xff0c;…

Codeforces Round #839 (Div. 3)(A~F)

A. AB?给出长度为3的字符串&#xff0c;计算字符串表示的表达式的值。思路&#xff1a;。AC Code&#xff1a;#include <bits/stdc.h>typedef long long ll; const int N 2e5 5; int t; std::string s;int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);…

立即放弃 TypeScript 的 17 个理由

如果你和我一样&#xff0c;你可能会因为被迫而使用 Typescript。你的公司决定它会成为未来的语言&#xff0c;所以你被迫学习它。起初&#xff0c;您很高兴使用 Typescript。你知道它有很大的潜力&#xff0c;可以帮助你制作更强大的应用程序。但在使用了一段时间后&#xff0…

3.深度学习前的预备知识

3.预备知识 目录 数据操作 N维数组创建数组访问元素 数据预处理读取数据集 处理缺失值转换为张量格式小结 练习线性代数 标量向量矩阵张量张量算法的基本性质降维非降维求和点积矩阵-向量积矩阵-矩阵乘法范数范数和目标 微积分 导数和微分偏导数梯度链式法则 自动微分 一个简…

万字讲解!进阶指针!

今天我们来看进阶指针&#xff0c;还没有看过初阶指针的话建议先看看初阶 (3条消息) 初阶指针---从入门到入坟_KLZUQ的博客-CSDN博客 目录 1. 字符指针 2. 指针数组 3. 数组指针 3.1 数组指针的定义 3.2 &数组名VS数组名 3.3 数组指针的使用 4. 数组参数、指针参数 …

使用Sivarc使PLC程序标准化

前言 由于公司最近做的项目都是同样的&#xff0c;并且都采用S7-1500/S7-1200 与G120 系列做为主控系统&#xff0c;所以我一直在思考一个问题&#xff1a;如何标准化并且快速的编程调试。这样可以极大的缩短项目的调试周期&#xff0c;减少公司工程成本&#xff0c;同时也免去…

英伟达发布528.02 WHQL 新驱动,支持4070 Ti

昨日&#xff0c;英伟达正式发布RTX 4070 Ti显卡&#xff0c;并马不停蹄发布了528.02 WHQL 驱动&#xff0c;支持4070 Ti&#xff0c;新硬件新驱动一次性齐活。 RTX 4070 Ti显卡在光线追踪游戏中的性能表现良好&#xff0c;在现代游戏如《瘟疫传说:安魂曲》&#xff0c;《战锤…

php如何接收支付宝应用网关发送的post请求

php如何接收支付宝应用网关发送的POST请求方式,参数又是GET请求的数据格式配置支付宝应用网关如何接收支付宝异步通知(应用网关接收请求)将&连接的参数分割成数组实例&#xff1a;难点配置支付宝应用网关 首先要在服务器上写一个接口,然后将接口的访问地址设置在支付宝应用…

Java中常用API总结(2)—— System类(含实例解读)

System类一、前言二、概述1.API帮助文档2.概述3.使用方式三、常用方法1.获取当前时间所对应的毫秒值1️⃣格式2️⃣实例3️⃣具体应用2.终止当前正在运行的Java虚拟机1️⃣格式2️⃣实例3.进行数值元素copy1️⃣格式2️⃣实例3️⃣注意事项四、结语一、前言 本文将讲述System类…

springsecurity认证流程

Authentication AuthenticationManager : 认证管理器 实现类&#xff1a; ProviderManager AuthenticationProvider &#xff1a; 实现类: DaoAuthenticationProviderRememberMeAuthenticationProvider 方法: authenticate()supports() : 判断当前AuthenticationProvider是…

dubbo学习笔记2(小d课堂)

dubbo核心架构及流程 企业中dubbo常见的多种开发方式 详解dubbo服务注册中心 Dubbo整合zookeeper 我们主要是改这部分&#xff1a; 然后我们启动本地的zookeeper&#xff0c;再去启动它&#xff1a; 会报错&#xff0c;这是说我们缺少响应的jar包&#xff1a; 就可以了。 我们提…

〖Python 数据库开发实战 - Python与Redis交互篇⑨〗- 利用 redis-py 实现模拟商品秒杀活动案例

文章目录 ❤️‍&#x1f525; 为什么要引入线程池技术 ❤️‍&#x1f525; 通过案例加深线程池技术原理的理解 ❤️‍&#x1f525; 实现多线程模拟商品秒杀案例 - 思路 ❤️‍&#x1f525; 实现多线程模拟商品秒杀案例 - 代码 今天的这一章节我们将来实现 “模拟商品秒杀活…

ES6 课程概述②

文章目录更好的 Unicode 支持更多的字符串 API3-3. [扩展]正则中的粘连标记模板字符串3-5. [扩展]模板字符串标记4-1. 参数默认值使用[扩展]对 arguments 的影响[扩展]留意暂时性死区4-2. 剩余参数4-3. 展开运算符对数组展开 ES6对对象展开 ES7函数柯里化4-5. 明确函数的双重用…

【菜菜的CV进阶之路 - 深度学习环境搭建】配置Ubuntu深度学习环境

六、配置Ubuntu深度学习环境 1、安装Google chrome 使用wget下载最新的Google Chrome .deb软件包&#xff1a; wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb更多地址可参考&#xff1a;在Deepin v20系统中下载和安装谷歌Chrome最新版de…

Vue学习笔记(一)

Vue学习笔记1. 什么是Vue2. 安装Vue2.1 使用独立版本2.2 使用CDN方式2.3 使用NPM方式3.Vue语法3.1 el挂载点3.2 data数据对象3.3 V-text 设置标签内的内容3.4 V-html3.5 V-on3.6 计数器3.7 v-show3.8 V-if3.9 v-bind3.10 v-for3.11 V-model4.class与style绑定5.表单输入绑定5.1…

【vue2】基础概念 01 (vue框架介绍、el、data、插值表达式)

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;vue框架介绍、结构元素详解&#xff08;el、data、插值表达式&#xff09; 目录&#xf…

《我是个怪圈》读书笔记

文章目录书籍信息论灵魂及其尺寸摇曳在恐惧与梦想之间的那只电灯泡&#xff08;取自拉塞尔埃德森的诗&#xff09;模式的因果潜力关于自我与符号副现象模式与可证性哥德尔的典型怪圈奇迹般步调划一的同步在公式与大整数之间翻转很大的整数与公式步调一致的移动质雅数怪圈论向下…