理解计算机系统_线程(九):线程安全问题

news2025/7/19 20:18:48

前言
       

        以<深入理解计算机系统>(以下称“本书”)内容为基础,对程序的整个过程进行梳理。本书内容对整个计算机系统做了系统性导引,每部分内容都是单独的一门课.学习深度根据自己需要来定

引入

        接续理解计算机系统_线程(八):并行-CSDN博客,内容包括12.7.1~12.7.3

概念浅析

        本书P716~P719讲了线程安全问题,笔者个人感觉不太好理解,从使用的角度对几个概念梳理.

        1.同步共享是紧密相连的.

                凡是说同步问题,必然牵涉到共享数据.再直白一点,函数体内部有全局变量.

        2.线程不安全函数=同步+无锁

        3.线程安全函数=同步+有锁

        4.可重入函数=不同步

        如图

同步再分析

        从函数,使用的角度再分析同步

        1>从函数角度来看,同步属于"程序副作用"(以前提过).同步可看作是多线程下的程序副作用.

        2>站在使用者的角度,同步应尽量避免(本书P716第1段:同步从根本上来说是很难的问题,他引出了在普通顺序程序中不会出现的问题.---黑体字是原话),在前一贴并行的讨论中,也是选择了绕开同步.

        当同步不可避免时,需要考虑线程安全(加锁)

线程安全

        概念:当且仅当被多个并发线程反复地调用时,他会一直产生正确的结果.这就是线程安全函数

        笔者用了个简单的视角来看待线程安全的函数:"同步加有锁"---当一个函数的定义中有全局变量,并且在访问全局变量时加上了锁(互斥锁),那他就是线程安全的函数.显然这种看法并不严谨(两点限制:一是目前除了锁以外没有保证线程安全的写法;二是笔者对于线程安全的知识仅来自于本书),除去以上两点限制,笔者的看法是可用的.

        本书P716开始介绍了四种线程不安全函数类,都可以概括在内,简单如下理解:

        第1类:不保护共享变量的函数

                线程函数中使用了共享变量,没加锁.---基础情况

        第2类:保持跨越多个调用的状态的函数

                本书举了一个例子,如图

                线程函数调用的函数中,使用了共享变量.---和1的情况差不多,只不过相当于包装了一层

                即使不考虑线程安全,这样写代码(程序副作用)也是比较"忌讳"的.原因是全局变量随时处于被更改的状态,不知道代码当前状态下的全局变量是哪一个了.解决办法在P718可重入性里讲了--传入指针,随时保持全局变量的更新.

                本书P716:使得像rand这样的函数线程安全的唯一方式是重写他,使得他不再使用任何static数据,而是依靠调用者在参数中传递状态信息.这样做的缺点是,程序员现在还要被迫修改调用程序中的代码.---黑体字是原话

                ---解读:笔者认为书中做法和线程安全无关,他说的意思是把程序副作用变为可重入函数,代码如下:

//函数定义
unsigned rand(int replace_data){
    replace_data=replace_data*1103515245+12543;
    return (unsigned)(replace_data>>16)%32768;
}

unsigned srand(unsigned new_seed){
    return new_seed;
}

//以下为调用
int random=srand(rand(1));

                和全局变量脱离关系(用的是局部变量),和线程安全更加无关了.

        第3类:返回指向静态变量的指针的函数.

                某些函数,例如ctime和gethostbyname,将计算结果放在一个static变量中,然后返回一个指向这个变量的指针.有两种方法来处理这类线程不安全函数.一种选择重写函数.一种选择就是使用加锁-复制技术.----黑体字是原话

                ---解读:实际上这是一种特别的例子.返回值既return了,又从形参返回.解决办法还是加锁.

        第4类,调用线程不安全函数的函数.        

        这4类线程不安全的函数,解决办法都是加锁.举的例子中有些比较特殊,不用过度解读. 

可重入性     

        本书原话:其特点在于他们具有这样一种属性:当他们被多个线程调用时,不会引用任何共享数据.         

        ---解读:线程安全或不安全,特点是函数体内部使用了共享数据,可重入函数没有共享数据,所以和线程安全无关.

显式可重入和隐式可重入

        显式可重入:如果所有的函数参数都是传值传递(即没有指针),并且所有的数据引用都是本地自动栈变量(即没有引用静态或全局变量),那么函数就是显式可重入的.

        隐式可重入:如果调用线程小心地传递指向非共享数据的指针,那么他是可重入的.

        特别注意:如果传递了指向全局变量的指针,他名义上是可重入,但又成为了线程不安全的函数.这一点书上写得很隐晦,但分析可以得出结果:如果线程函数中调用rand_r,而rand_r传入了全局变量的指针给nextp,不加锁仍然会出现同步问题.---如果笔者的认识是错的,那么更简单.

在线程化的程序中使用已存在的库函数

        如图

        为保险起见,给线程安全版本传入全局变量的副本(copy),而不是直接传全局变量

小结

        线程安全的理解

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

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

相关文章

vue3基本类型和对象类型的响应式数据

vue3中基本类型和对象类型的响应式数据 OptionsAPI与CompstitionAPI的区别 OptionsAPI Options API • 特点&#xff1a;基于选项&#xff08;options&#xff09;来组织代码&#xff0c;将逻辑按照生命周期、数据、方法等分类。• 结构&#xff1a;代码按照 data 、 methods…

3.8.4 利用RDD实现分组排行榜

本实战任务通过Spark RDD实现学生成绩的分组排行榜。首先&#xff0c;准备包含学生成绩的原始数据文件&#xff0c;并将其上传至HDFS。接着&#xff0c;利用Spark的交互式环境或通过创建Maven项目的方式&#xff0c;读取HDFS中的成绩文件生成RDD。通过map操作将数据映射为二元组…

python web flask专题-Flask入门指南:从安装到核心功能详解

Flask入门指南&#xff1a;从安装到核心功能详解 Flask作为Python最流行的轻量级Web框架之一&#xff0c;以其简洁灵活的特性广受开发者喜爱。本文将带你从零开始学习Flask&#xff0c;涵盖安装配置、项目结构、应用实例、路由系统以及请求响应处理等核心知识点。 1. Flask安…

【HW系列】—web组件漏洞(Strtus2和Apache Log4j2)

本文仅用于技术研究&#xff0c;禁止用于非法用途。 文章目录 Struts2Struts2 框架介绍Struts2 历史漏洞汇总&#xff08;表格&#xff09;Struts2-045 漏洞详解 Log4j2Log4j2 框架介绍Log4j2 漏洞原理1. JNDI 注入2. 利用过程 Log4j2 历史漏洞JNDILDAP 反弹 Shell 流程 Strut…

机器学习知识体系:从“找规律”到“做决策”的全过程解析

你可能听说过“机器学习”&#xff0c;觉得它很神秘&#xff0c;像是让电脑自己学会做事。其实&#xff0c;机器学习的本质很简单&#xff1a;通过数据来自动建立规则&#xff0c;从而完成预测或决策任务。 这篇文章将用通俗的语言为你梳理机器学习的知识体系&#xff0c;帮助…

STM32之FreeRTOS移植(重点)

RTOS的基本概念 实时操作系统&#xff08;Real Time Operating System&#xff09;的简称就叫做RTOS&#xff0c;是指具有实时性、能支持实时控制系统工作的操作系统&#xff0c;RTOS的首要任务就是调度所有可以利用的资源来完成实时控制任务的工作&#xff0c;其次才是提高工…

R语言科研编程-标准偏差柱状图

生成随机数据 在R中&#xff0c;可以使用rnorm()生成正态分布的随机数据&#xff0c;并模拟分组数据。以下代码生成3组&#xff08;A、B、C&#xff09;随机数据&#xff0c;每组包含10个样本&#xff1a; set.seed(123) # 确保可重复性 group_A <- rnorm(10, mean50, sd…

OpenGL Chan视频学习-11 Uniforms in OpenGL

bilibili视频链接&#xff1a; 【最好的OpenGL教程之一】https://www.bilibili.com/video/BV1MJ411u7Bc?p5&vd_source44b77bde056381262ee55e448b9b1973 函数网站&#xff1a; docs.gl 说明&#xff1a; 1.之后就不再单独整理网站具体函数了&#xff0c;网站直接翻译…

GitLab 从 17.10 到 18.0.1 的升级指南

本文分享从 GitLab 中文本 17.10.0 升级到 18.0.1 的完整过程。 升级前提 查看当前安装实例的版本。有多种方式可以查看&#xff1a; 方式一&#xff1a; /help页面 可以直接在 /help页面查看当前实例的版本。以极狐GitLab SaaS 为例&#xff0c;在浏览器中输入 https://ji…

产业集群间的专利合作关系

需要准备的文件&#xff1a; 全国的专利表目标集群间的企业名单 根据专利的共同申请人&#xff0c;判断这两家企业之间存在专利合作关系。 利用1_filter_patent.py&#xff0c;从全国的3000多万条专利信息中&#xff0c;筛选出与目标集群企业相关的专利。 只要专利的申请人包…

KT6368A通过蓝牙芯片获取手机时间详细说明,对应串口指令举例

一、功能简介 KT6368A双模蓝牙芯片支持连接手机&#xff0c;获取手机的日期、时间信息&#xff0c;可以同步RTC时钟 1、无需安装任何app&#xff0c;直接使用系统蓝牙即可实现 2、同时它不影响音频蓝牙&#xff0c;还支持一些简单的AT指令进行操作 3、实现的方式&#xff1…

计算机网络实验课(二)——抓取网络数据包,并实现根据条件过滤抓取的以太网帧,分析帧结构

文章目录 一、添加控件二、代码分析2.1 代码2.2 控件初始化2.3 打开和关闭设备2.4 开始和结束捕获2.5 设置捕获条件2.6 捕获数据包 三、运行程序四、结果分析 提要&#xff1a;如果你通过vs打开.sln文件&#xff0c;然后代码界面或者前端界面都没找到&#xff0c;视图里面也没找…

78. Subsets和90. Subsets II

目录 78.子集 方法一、迭代法实现子集枚举 方法二、递归法实现子集枚举 方法三、根据子集元素个数分情况收集 方法四、直接回溯法 90.子集二 方法一、迭代法实现子集枚举 方法二、递归法实现子集枚举 方法三、根据子集元素个数分情况收集 方法四、直接回溯法 78.子集…

ElasticSearch整合SpringBoot

ElasticSearch 整合SpringBoot ES官方提供了各种不同语言的客户端。用来操作ES。这些客户端的本质就是组装DSL语句&#xff0c;通过HTTP请求发送给ES。 设计索引库 跟据数据库的表结构进行ES索引库的创建时。如果字段需要进行倒排索引的时候请为它指定分词器。如果该字段不是…

2025上半年软考高级系统架构设计师经验分享

笔者背景 笔者在成都工作近7年&#xff0c; 一直担任研发大头兵&#xff0c;平日工作主要涵盖应用开发&#xff08;Java&#xff09;与数仓开发&#xff0c;对主流数据库、框架等均有涉猎&#xff0c;但谈不上精通。 最近有一些职业上的想法&#xff0c;了解到软考有那么一丁点…

uni-app学习笔记十二-vue3中创建组件

通过组件&#xff0c;可以很方便地实现页面复用&#xff0c;减少重复页面的创建&#xff0c;减少重复代码。一个页面可以引入多个组件。下面介绍在HBuilder X中创建组件的方法&#xff1a; 一.组件的创建 1.选中项目&#xff0c;右键-->新建目录(文件夹)&#xff0c;并将文…

一键启动多个 Chrome 实例并自动清理的 Bash 脚本分享!

目录 一、&#x1f4e6; 脚本功能概览 二、&#x1f4dc; 脚本代码一览 三、&#x1f50d; 脚本功能说明 &#xff08;一&#xff09;✅ 支持批量启动多个 Chrome 实例 &#xff08;二&#xff09;✅ 每个实例使用独立用户数据目录 &#xff08;三&#xff09;✅ 启动后自…

4 月 62100 款 App 被谷歌下架!环比增长 28%

大家好&#xff0c;我是牢鹅&#xff01;上周刚刚结束的 2025 年 Google I/O 开发者大会&#xff0c; Google Play 带来了一系列的更新&#xff0c;主要围绕提升优质 App 的"发现"、"互动"和"收入"三大核心内容。 这或许正是谷歌生态的一个侧影…

mediapipe标注视频姿态关键点(基础版加进阶版)

前言 手语视频流的识别有两种大的分类&#xff0c;一种是直接将视频输入进网络&#xff0c;一种是识别了关键点之后再进入网络。所以这篇文章我就要来讲讲如何用mediapipe对手语视频进行关键点标注。 代码 需要直接使用代码的&#xff0c;我就放这里了。环境自己配置一下吧&…

PCtoLCD2002如何制作6*8字符

如何不把“等比缩放”前的打勾取消&#xff0c;则无法修改为对应英文字符为6*8。 取消之后就可以更改了&#xff01;