Linux 线程安全

一、线程安全的概念

线程安全即就是在多线程运行的时候,不论线程的调度顺序怎样,最终的结果都是 一样的、正确的。那么就说这些线程是安全的。

二、如何保证线程安全

1.线程同步

保证同一时刻只有一个线程访问临界资源。线程同步的方法有4种,信号量、互斥锁、读写锁、条件变量。

2.使用线程安全的函数

在多线程中使用线程安全的函数(可重入函数),所谓线程安全的函数指的是:如果一个函数能被多个线程同时调用且不发生竟态条件,则我们程它是线程安全的。

三、线程安全的函数的应用

【例】在两个线程中分别对一个字符串进行分隔的问题

字符串分隔函数:

在这里插入图片描述
第一次调用结束后,第二次调用的时候给第一个参数传空,就可以沿着原来的字符串继续分隔拿到第二段分割好的字符串。

第一次没有使用线程安全函数的情况的代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<string.h>
#include<semaphore.h>void* fun(void*arg)
{char arr[128]="a b c d e f";//定义一个字符串//以空格作为字符串buff的分隔符,将分隔好的字符串内容返回给schar* s =strtok(arr," ");while(s!=NULL)//如果s为空结束循环,s为空说明字符串buff已经被分隔完了{printf("fun分隔字符串arr得到的内容为:%s\n",s);s=strtok(NULL," ");sleep(1);}
}int main()
{pthread_t id;pthread_create(&id,NULL,fun,NULL);char brr[128]="1 2 3 4 5 6";char* p =strtok(brr," ");while(p!=NULL){printf("main分隔字符串brr得到的内容为:%s\n",p);p=strtok(NULL," ");sleep(1);}pthread_join(id,NULL);exit(0);
}

运行结果:

在这里插入图片描述

结果分析:

这样的运行结果并不是我们所期望的结果,我们希望fun函数分隔字符串arr,main函数分隔字符串brr,但是上面的程序中,main函数却去分隔了fun函数中的字符串arr,子线程fun和主线程main之间彼此影响,然而这并不是我们所期望的。

出现上面结果的原因是,strtok()函数的内部有一个指针用来记录把字符串分隔到哪个位置,这个指针大概率是一个静态变量指针,这样做有一个弊端,就是在线程fun和线程main中调用strtok()这个函数的时候访问静态变量是同一快空间,当线程fun中去调用这个strtok()函数去记录当前的字符串arr被分隔到了哪个位置,但是在线程main中也调用了strtok()这个函数去记录当前的字符串brr被分隔到了哪个位置,意味着线程fun和线程main都要去修改同一块空间中的内容。也就是说,fun线程和main线程都在调用strtok()这个函数,在这两个线程中调用strtok()函数的两条路径同时在执行,strtok()函数中的那个记录字符串分隔位置的指针是一个静态变量,我们在程序中看到在线程fun和main中好像各自都给strtok()函数的这个静态变量分配了一块空间,但是其实不是的,因为在物理内存空间上,这两个线程中strtok()函数的这两块静态变量的空间用的是同一块空间。所以,如果在某一个线程中修改了这块空间中静态变量的值,那么对于另外一个线程来说,这个静态变量的值也发生了变化,因此,这两个线程在运行的时候就会彼此影响,导致最终输出的结果并不是我们所期望的。也就是如果要在多线程中去同时strtok()方法,那么是不可以的,因为strtok()这个方法不是线程安全的。strtok()方法压根就不可以在多线程中使用,因为strtok()函数内部有静态变量,在多线程中同时执行得话,每条路径访问到的静态变量就是同一个,每个线程去记录这个静态变量得信息的时候就会冲突,信息就会被覆盖,程序的执行结果就会产生问题。

比如上图的结果就是因为,main线程和fun线程中调用strtok()函数这两条路径同时执行,第一次分隔之后都得到了对应被分隔的字符串,但是第二次分隔的时候,因为传入的参数为NULL,要从上一次结束的位置去继续分隔字符串,由于上一次分隔字符串结束的位置在fun线程中的arr字符串中,所以当main线程执行的时候,它接收到的被分隔好的字符串是从arr中分隔来的,后续分隔的字符串也都是对arr字符串进行分隔。解决这个问题的思路就是,让两个线程自己用自己的空间,分别记录当前字符串被分隔到哪里,就需要用到这个函数的线程安全版本strtok_r()。

有一类库函数之前都不是线程安全的,引用多线程之后都会存在问题,为之实现了一个多线程的版本,称之为线程安全的版本。这样的函数有很多,比如当前的strtok()函数,它的线程安全版本如下:

在这里插入图片描述

第三个参数 saveptr:是一个二级指针,它需要传入一个指针,传入一个指针以后,通过传入得指针来记录当前字符串被分隔到哪里。这样的话每一个线程都会自己定义这样一个指针,来分别记录它们分隔得字符串分隔到哪个位置,这时,两个线程就不共用同一块空间了。

使用线程安全函数strtok_r()的代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<string.h>
#include<semaphore.h>void* fun(void*arg)
{char arr[128]="a b c d e f";//定义一个字符串//以空格作为字符串buff的分隔符,将分隔好的字符串内容返回给schar* n=NULL;//定义一个空指针,用这个指针就用来记录字符串分隔的位置char* s =strtok_r(arr," ",&n);while(s!=NULL)//如果s为空结束循环,s为空说明字符串buff已经被分隔完了{printf("fun分隔字符串arr得到的内容为:%s\n",s);s=strtok_r(NULL," ",&n);sleep(1);}
}int main()
{pthread_t id;pthread_create(&id,NULL,fun,NULL);char brr[128]="1 2 3 4 5 6";char* m=NULL;char* p =strtok_r(brr," ",&m);while(p!=NULL){printf("main分隔字符串brr得到的内容为:%s\n",p);p=strtok_r(NULL," ",&m);sleep(1);}pthread_join(id,NULL);exit(0);
}

运行结果:

在这里插入图片描述
此时,就是fun线程和main线程不再共用一块空间了,它们各自有各自的空间来来记录自己所分隔的字符串分隔到了哪个位置。这样两个线程同时执行的时候彼此之间就不会影响了,程序也不会产生错误的结果。

四、总结

在多线程中使用库函数的时候一定要使用线程安全版本,这样才能保证线程安全。线程安全指的就是,多线程程序无论调度顺序如何,都能保证程序的结果是正确的,就说该程序处于线程安全的状态。主要的方法就是线程同步和线程安全函数。

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

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

相关文章

成都瀚网科技:抖店如何经营?

作为热门的短视频分享平台&#xff0c;抖音不仅是一种娱乐工具&#xff0c;更是一个蕴藏着无限商机的电商平台。开店、抖音下单成为很多人的选择。那么&#xff0c;抖音如何开店、下单呢&#xff1f; 1、如何在抖音上开店和下单&#xff1f; 注册账号&#xff1a;首先&#xff…

重要岗位人员脱岗预警 脱岗监测预警算法

重要岗位人员脱岗预警 脱岗监测预警算法通过yolov8网络模型深度学习算法&#xff0c;重要岗位人员脱岗预警 脱岗监测预警算法对现场人员行为进行实时监测和识别&#xff0c;通过算法识别脱岗、睡岗和玩手机等异常行为&#xff0c;实现对人员行为的预警和告警。YOLOv8是目前YOLO…

初步认识OSPF的大致内容(第三课)

1 路由的分类 直连路由(Directly Connected Route)是指网络拓扑结构中相邻两个网络设备直接相连的路由,也称为直接路由。如果两个设备属于同一IP网络地址,那么它们就是直连设备。直连路由表是指由计算机系统生成的一种用于路由选择的表格,其中记录着直连路由的信息。直连…

基于微信小程序中小学生练字书法家校联合系统

对于一些学生和书法爱好者来说&#xff0c;需要时时刻刻了解&#xff0c;自己及自己所喜欢的书法的相关信息&#xff0c;书法作业的相关事宜&#xff0c;学生作业的相关信息&#xff0c;比如查询教学进度、书法作业等这样才能更好的推动我国的书法事业发展,为此今后有必要对书法…

流处理详解

【今日】 目录 一 Stream接口简介 Optional类 Collectors类 二 数据过滤 1. filter()方法 2.distinct()方法 3.limit()方法 4.skip()方法 三 数据映射 四 数据查找 1. allMatch()方法 2. anyMatch()方法 3. noneMatch()方法 4. findFirst()方法 五 数据收集…

【uniapp】微信小程序 , 海报轮播图弹窗,点击海报保存到本地,长按海报图片分享,收藏或保存

uivew 2.0 uniapp 海报画板 DCloud 插件市场 第一步&#xff0c;下载插件并导入HbuilderX 第二步&#xff0c;文件内 引入 海报组件 <template><painter ref"haibaorefs"></painter> <template> <script>import painter from /comp…

如何在windows下使用masm和link对汇编文件进行编译

前言 32位系统带有debug程序&#xff0c;可以进行汇编语言和exe的调试。但真正的汇编编程是“编辑汇编程序文件(.asm)->编译生成obj文件->链接生成exe文件”。下面&#xff0c;我就来说一下如何在windows下使用masm调试&#xff0c;使用link链接。 1、下载相应软件 下载…

LoadRunner操作教程

日升时奋斗&#xff0c;日落时自省 目录 1、Virtual User Generator &#xff08;VUG&#xff09; 1.1、WebTours系统 1.1.1、WebTours启动 1.1.2、WebTours配置 1.2、脚本录制 1.3、编译 1.4、脚本运行 1.5、加强脚本 1.5.1、事务插入 1.5.2、插入集合点 1.5.3、参…

解决`idea`中`database`工具查询起别名乱码问题

文章目录 解决idea中database工具查询起别名乱码问题场景复现如何解决方式一 设置编码方式二&#xff1a;修改字体 原因说明 解决idea中database工具查询起别名乱码问题 场景复现 使用Idea做查询的并且起别名出现了中文乱码 如何解决 方式一 设置编码 settings->输入框输…

如何使用LLM实现文本自动生成视频

推荐&#xff1a;使用 NSDT场景编辑器 助你快速搭建可二次编辑的3D应用场景 介绍 基于扩散的图像生成模型代表了计算机视觉领域的革命性突破。这些进步由Imagen&#xff0c;DallE和MidJourney等模型开创&#xff0c;展示了文本条件图像生成的卓越功能。有关这些模型内部工作的…

龙芯2K1000LA移植交叉编译环境以及QT

嵌入式大赛结束了&#xff0c;根据这次比赛中记的凌乱的笔记&#xff0c;整理了一份龙芯2K1000LA的环境搭建过程&#xff0c;可能笔记缺少了一部分步骤或者错误&#xff0c;但是大致步骤可以当作参考。 一、交叉编译工具链 下载连接&#xff1a;龙芯 GNU 编译工具链 | 龙芯开…

【PHP】echo 输出数组报Array to string conversion解决办法

代码&#xff1a; <?PHP echo "Hello World!";$demoName array("kexuexiong","xiong");echo "<pre>";var_dump($demoName);echo $demoName; print_r($demoName);echo "</pre>"; ?>输出结果&#xff1…

Anaconda Conda实现Python多环境管理

Anaconda Conda实现Python多环境管理 Python多环境AnacondaConda环境管理下载安装镜像配置环境管理常用命令创建Python3.10环境 Python多环境 Python多环境指的是在同一台计算机上同时安装并管理多个不同的Python版本。可以在不同版本的Python之间切换&#xff0c;并确保每个项…

ethers.js1:ethers的安装和使用

ethers官方文档&#xff1a;Documentation 1、ethers简介&#xff1a; ethers.js是一个完整而紧凑的开源库&#xff0c;用于与以太坊区块链及其生态系统进行交互。如果你要写Dapp的前端&#xff0c;你就需要用到ethers.js。 与更早出现的web3.js相比&#xff0c;它有以下优点…

05.Image Captioning with Semantic Attention

目录 前言泛读摘要Introduction创新/贡献点Related Work 精读输入的注意力模型输出的注意力模型模型学习视觉属性/概念预测实验MS-COCO的性能实验分析 Conclusion 代码略 前言 本课程来自深度之眼《多模态》训练营&#xff0c;部分截图来自课程视频。 文章标题&#xff1a;Ima…

工地扬尘自动监测识别算法

工地扬尘自动监测识别系统通过yolov7python网络模型深度学习算法模型&#xff0c;扬尘自动监测识别算法能够全天候、全方位地观测扬尘情况。YOLOv7 的策略是使用组卷积来扩展计算块的通道和基数。研究者将对计算层的所有计算块应用相同的组参数和通道乘数。然后&#xff0c;每个…

EasyExcel+POI制作带有有效性校验及下拉联动的Excel模板

文章目录 1.背景2.实现功能的Excel特性2.1.特性介绍2.2.下拉框联动2.3.单元格自动匹配Id2.4.错误提示 3.代码实现3.1.基础流程代码3.2.名称管理器配置3.3.有效性配置3.4.函数填充3.5.其他补充 4.总结 1.背景 最近在做一个CRM系统的人员销售目标导入的相关需求&#xff0c;需要…

eslint

什么是eslint ESLint 是一个根据方案识别并报告 ECMAScript/JavaScript 代码问题的工具&#xff0c;其目的是使代码风格更加一致并避免错误。 安装eslint npm init eslint/config执行后会有很多选项&#xff0c;按照自己的需求去选择就好&#xff0c;运行成功后会生成 .esli…

docker 重装提示 Exising installation is up to date 解决方法

Windows Docker 重装提示 Exising installation is up to date 解决方法 出现这个问题是因为卸载Docker没有卸载干净&#xff0c;导致无法重装 解决方法&#xff1a; 按下WindowR唤起命令输入界面&#xff0c;输入 regedit 打开注册表编辑在地址栏输入HKEY_LOCAL_MACHINE\SOFTW…

MQ消息队列(主要介绍RabbitMQ)

消息队列概念&#xff1a;是在消息的传输过程中保存消息的容器。 作用&#xff1a;异步处理、应用解耦、流量控制..... RabbitMQ&#xff1a; SpringBoot继承RabbitMQ步骤&#xff1a; 1.加入依赖 <dependency><groupId>org.springframework.boot</groupId&g…