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

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


我们定义四类线程不安全函数:

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

将这类线程不安全函数变为线程安全的,相对比较容易:利用像P和V操作这样的同步操作来保护共享变量。这个方法的优点是在调用程序中不需要做任何修改,缺点是同步操作将减慢程序的执行时间。

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

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

某些函数(如gethostbyname)将计算结果放在静态结构中,并返回一个指向这个结构的指针。如果我们从并发线程中调用这些函数,那么将可能发生灾难,因为正在被一个线程使用的结果会被另一个线程悄悄地覆盖了。

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


我们再来看看什么是可重入函数

重入:即重复调用,函数被不同的流调用,有可能会出现第一次调用还没返回时就再次进入该函数开始下一次调用。

可重入:当程序被多个线程反复执行,产生的结果正确。

可重入函数:如果一个函数只访问自己的局部变量或参数,称为可重入函数。

不可重入:当程序被多个线程反复调用,产生的结果出错。

不可重入函数:当函数访问一个全局的变量或者参数时,有可能因为重入而造成混乱,像这样的函数称为不可重入函数。


可重入特点:

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

不可重入特点:

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

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

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

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


可重入函数通常要比不可重入的线程安全函数效率高一些,因为它们不需要同步操作。



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

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

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

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

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

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


总结:
1、判断一个函数是不是可重入函数,在于判断其能否可以被打断,打断后恢复运行能够得到正确的结果。(打断执行的指令序列并不改变函数的数据)
判断一个函数是不是线程安全的,在于判断其能否在多个线程同时执行其指令序列的时候,保证每个线程都能够得到正确的结果。
2、如果一个函数对多个线程来说是可重入的,则说这个函数是线程安全的,但这并不能说明对信号处理程序来说该函数也是可重入的。
3、如果函数对异步信号处理程序的重入是安全的,那么就可以说函数是"异步-信号安全"的。

4、可重入概念只和函数访问的变量类型有关,和是否使用锁没有关系!而线程安全和锁的使用关系密切,很多时候线程安全是靠锁来保证的。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值