专栏首页CSDN搜“看,未来”可重入函数对于线程安全的意义(附函数表)

可重入函数对于线程安全的意义(附函数表)

是什么

什么是可重入函数,什么是不可重入函数?

不可重入函数: 在并发服务器中,经常会出现多个任务调用同一个函数的情况,比方说后端服务器使用多线程同时对数据库进行访问操作。如果有一个函数不幸被设计成为这样:那么不同任务调用这个函数时可能修改其他任务调用这个函数的数据,从而导致不可预料的后果。这样的函数是不安全的函数,也叫不可重入函数。 (其实也没什么不可预料的,就是服务器崩了呗,然后我就完了呗)

可重入函数: 所谓可重入是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会出错。 一个可重入的函数简单来说就是可以被中断的函数。

可重入函数的分类 (1)显式可重入函数 如果所有函数的参数都是传值传递的(没有指针),并且所有的数据引用都是本地的自动栈变量(也就是说没有引用静态或全局变量),那么函数就是显示可重入的,也就是说不管如何调用,我们都可断言它是可重入的。 (2)隐式可重入函数 可重入函数中的一些参数是引用传递(使用了指针),也就是说,在调用线程小心地传递指向非共享数据的指针时,它才是可重入的。 可重入函数可以有多余一个任务并发使用,而不必担心数据错误,相反,不可重入函数不能由超过一个任务所共享,除非能确保函数的互斥(或者使用信号量,或者在 代码的关键部分禁用中断)。可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据,可重入函数要么使用本地变量,要么在使用全局变量时保护自己 的数据。

为什么

为什么有的函数可重入,又有的函数不可重入?

  1. 为什么可重入

一个可重入函数可以被多个执行流重复进入,内部使用的数据都应该来自于自身的栈空间,包括返回值也不应该是全局或者静态的,可以允许有该函数的多个副本在运行,而正是因为其中的操作数据都来自于自身的栈空间,而每次调用函数会开辟不同的栈空间,因此二者互不影响。

  1. 为什么不可重入 不可重入的特点:如果一个函数符合以下条件之一则是不可重入的 (1)调用了malloc/free函数,因为malloc函数是用全局链表来管理堆的 (2)调用了标准I/O库函数,标准I/O库的很多实现都是以不可重入的方式使用全局的数据结构 (3)可重入体内使用了静态的数据结构

怎么做

  1. 任何确保写的函数可重入

1.不在函数内部使用静态或全局变量 2.不返回静态或全局变量,所有数据都有函数的调用者提供。 3.使用本地数据,或通过制作全局数据的本地拷贝来保护全局数据 4.不调用不可重入函数

如果确实需要访问全局变量(包括 static),一定要注意实施互斥手段。可重入函数在并行运行环境中非常重要,但是一般要为访问全局变量付出一些性能代价。 编写可重入函数时,若使用全局变量,则应通过关中断、信号量(即P、V操作)等手段对其加以保护。

举例

Linux下常见可重入函数

上面那个不够满足的话,看下面这个:

POSIX.1-20001标准规定,所有的标准库函数都必须是可重入函数,除了以下这些:

当然,咱自己写出不可重入函数就另当别论了。

其他

线程安全与可重入函数的区别 (1)、可重入函数是线程安全函数的一种,其特点在于它们被多个线程调用时,不会引用任何共享数据。 (2)、线程安全是在多个线程情况下引发的,而可重入函数可以在只有一个线程的情况下来说。 (3)、线程安全不一定是可重入的,而可重入函数则一定是线程安全的。 (4)、如果一个函数中有全局变量,那么这个函数既不是线程安全也不是可重入的。 (5).如果将对临界资源的访问加上锁,则这个函数是线程安全的,但如果这个重入函数若锁还未释放则会产生死锁,因此是不可重入的。 (6)、线程安全函数能够使不同的线程访问同一块地址空间,而可重入函数要求不同的执行流对数据的操作互不影响使结果是相同的。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【C++】勉强能看的线程池详解

    线程池这东西,用了几次还是不得其解,简直是:求之不得,寤寐思服。悠哉悠哉,辗转反侧。

    看、未来
  • 【C++】勉强能看的线程池详解

    线程池这东西,用了几次还是不得其解,简直是:求之不得,寤寐思服。悠哉悠哉,辗转反侧。

    看、未来
  • 学以致用C++设计模式 之 “观察者模式”

    看武侠片的时候,经常会看到某个倒霉蛋,不小心拉到了哪根线,然后就出现了漫天箭雨,运气不好就射成箭猪了,没被射死呢,又飞来一堆木头,没点本事就被击飞了,就算躲过一...

    看、未来
  • 搜索引擎优化(SEO) 基础常识

    在移动互联网迅猛发展的今天,各种APP、小程序满天飞,针对网页的搜索引擎优化(SEO)对于现今的企业来说已经不是头等重要的事情了。但是如果公司的SEO做得好的话...

    FungLeo
  • BP神经网络-ANN发展

    Dear junqiang: Hello 今天是“一天一文”的第18天。继续关于AI里面最重要的神经网络的知识分享。 昨天的文章说了关于ANN的基础 —— 单层...

    企鹅号小编
  • MapReduce之自定义InputFormat

    将多个小文件合并成一个SequenceFile文件(SequenceFile文件是Hadoop用来存储二进制形式的key-value(bytes) 对的文件格式...

    爱学习的孙小白
  • 小白教程,Springboot项目搭建(前端到数据库,超详细)

    这是一篇入门Springboot的小白教程,但是看到写得这么详细,说不定有同学需要呢?大神看到这里就可以跳过了哈。

    java思维导图
  • 设计原则之里氏替换原则(LSP)

    里氏替换原则是在做继承设计时需要遵循的原则,不遵循了 LSP 的继承类会带来意想不到的问题。

    Dylan Liu
  • Java性能测试中两种锁的实现

    同步是使所有并发线程在执行中保持同步的过程。同步避免了由于共享内存视图不一致而导致的内存一致性错误。当方法被声明为同步时,该线程持有监视器或锁定对象为这个方法的...

    FunTester
  • 我是一个什么风格的管理者?

    昨天一口气看了好几篇刘建国老师,在极客时间《技术管理实战36讲》的文章,看地非常过瘾。

    赵成

扫码关注云+社区

领取腾讯云代金券