-对比线程安全和可重入函数


线程安全


一个函数被称为线程安全的(thread-safe),当且仅当被多个并发进程反复调用时,它会一直产生正确的结果。反之,如果一个函数不是线程安全的,我们就说它是线程不安全的(thread-unsafe)。所以,有这么四类函数称为线程不安全的

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

根据线程的同步与互斥,也就是当两个线程同时访问到同一个临界资源的时候,如果 对临界资源的操作不是原子的就会产生冲突 ,使得结果并不如最终预期的那样。


如何避免

         1, 减少对临界资源的依赖,尽量避免访问全局变量,静态变量或其它共享资源,如果必须要使用共享资源,所有使用到的地方必须要进行互斥锁 (Mutex) 保护;

         2, 线程安全的函数所调用到的函数也应该是线程安全的,如果所调用的函数不是线程安全的,那么这些函数也必须被互斥锁 (Mutex) 保护;




可重入函数


 函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数,这称为重入

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

      相对应的,当一个执行流因为异常或者被内核切换而中断正在执行的函数而转为另外一个执行流时,当后者的执行流对同一个函数的操作并不影响前一个执行流恢复后执行函数产生的结果,我们就称这个函数为可重入函数可重入函数只访问自己的局部变量或参数其实总结就是:一个可重入函数可以被多个执行流重复进入,内部使用的数据都应该来自于自身的栈空间,包括返回值也不应该是全局或者静态的,可以允许有该函数的多个副本在运行,而正是因为其中的操作数据都来自于自身的栈空间,而每次调用函数会开辟不同的栈空间,因此二者互不影响。


可重入函数特点:


由于可重入函数多次调用不会出错,因此可重入函数不用担心数据会被破坏。可重入函数任何时候都可以被中断,一段时间后又可以运行,而相应的数据不会丢失。可重入函数只使用局部变量,即保存在CPU寄存器或者堆栈中;或者如果使用全局变量时,则要对全局变量予以保护。


不可重入函数特点:


如果一个函数符合以下条件之一的,则是不可重入的:

(1)调用了malloc/free函数,因为malloc函数是用全局链表来管理堆的。

(2)调用了标准I/O库函数,标准I/O库的很多实现都以不可重入的方式使用全局数据结构

(3)可重入体内使用了静态的数据结构。



可重入函数与线程安全的区别与联系:


(1)线程安全是在多个线程情况下引发的,而可重入函数可以在只有一个线程的情况下来说。

(2)线程安全不一定是可重入的,而可重入函数则一定是线程安全的。

(3)如果一个函数中有全局变量,那么这个函数既不是线程安全也不是可重入的。

(4)如果将对临界资源的访问加上锁,则这个函数是线程安全的,但如果这个重入函数若锁还未释放则会产生死锁,因此是不可重入的。

(5)线程安全函数能够使不同的线程访问同一块地址空间,而可重入函数要求不同的执行流对数据的操作互不影响使结果是相同的。












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值