线程安全与可重入函数之间的区别

今天,学到了两个概念。线程安全、与可重入函数 这个都是关于多线程的,下面我们来看看这两个概念到底有什么不同之处。

先来看看这两个概念

1、什么是可重入函数

函数被不同的控制流程调用,有时会在之前的函数正在访问函数变量的时候,线程被切出去执行别的流程再次在别的线程放访问当前的函数,这个过程叫做是重入。
 详细说的话,

假设当前的程序是多线程的程序 ,当程序运行到某一个函数的时候,可能因为硬件中断或者异常而使得在用户正在执行的代码暂时终端转而进入你内核,这个时候如有一个信号需要被处理,而处理的这个信号的时候又会重新调用刚才中断的函数,如果函数内部有一个全局变量需要被操作,那么,当信号处理完成之后重新返回用户态恢复中断函数的上下文再次继续执行的时候,对同一个全局变量的操作结果可能就会发生改变而并不如我们预期的那样,这样的函数被称为不可重入函数。例如在进行链表的的插入时,插入函数访问一个全局链表,有可能因为重入而造成错乱。

相对应的,当一个执行流因为异常或者被内核切换而中断正在执行的函数而转为另外一个执行流时,当后者的执行流对同一个函数的操作并不影响前一个执行流恢复后执行函数产生的结果,我们就称这个函数为可重入函数

可重入函数只访问自己的局部变量或参数

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

2、什么是线程安全

 当多个线程类并发操作某类的某个方法,(在该方法内部)来修改这个类的某个成员变量的值,不会出错,则我们就说,该的这个方法是线程安全的。

  某类的某方法是否线程安全的关键是:

  (1) 该方法是否修改该类的成员变量;

  (2) 是否给该方法加锁(是否用synchronized关键字修饰)

所以,有这么四类函数称为线程不安全的

1、不保护共享变量的函数;
2、函数状态随着调用改变的函数;
3、返回指向静态变量指针的函数;
4、调用线程不安全函数的函数;

如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码如果每次运行结果和运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。或者说一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。
        线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。
一般来说,一个函数被称为线程安全的,当且仅当被多个并发线程反复调用时,它会一直产生正确的结果

3、可重入函数的分类

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

一个可重入函数需要满足的是:

1、不使用全局变量或静态变量;
2、不使用用malloc或者new开辟出的空间;
3、不调用不可重入函数;
4、不返回静态或全局数据,所有数据都有函数的调用者提供;
5、使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据;

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

4、线程安全与可重入函数的区别

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值