您的位置:首页 > 其它

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

2016-07-13 13:41 267 查看
1、可重入函数
1)举例说明:



main函数调用insert函数向一个链表head中插入节点node1,插入操作分为两步,刚做完第一步的时候,因为硬件中断使进程切换到内核,再次回用户态之前检查到有信号待处理,于是切换到sighandler函数sighandler也调用insert函数向同一个链表head中插入节点node2,插入操作的两步都做完之后从sighandler返回内核态,再次回到用户态就从main函数调用的insert函数中继续往下执行,先前做第一步之后被打断,现在继续做完第二步。结果是,main函数和sighandler先后向链表中插入两个节点,而最后只有一个节点真正插入链表中了。

insert函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数,这称为重入。
insert函数访问一个全局链表,有可能因为重入而造成错乱,像这样的函数称为不可重入函数。
反之,如果一个函数只访问自己的局部变量或参数,则称为可重入(Reentrant)函数。

2)可重入性(reentrant)针对函数,它有两个方面的内涵:
(1)可并行/并发,同时进入:指可重入函数被某任务调用时,其它任务可同时进行调用而不产生错误的结果;或称在相同的输入情况下可重入函数的执行所产生的效果,并不因其并发的调用而产生不同,也称并发安全。

(2)中断后可重新进入:指可重入函数可被任意的中断,当中断执行完毕,返回断点可以继续正确的运行下去;或称在相同的输入情况下可重入函数的执行所产生的结果,并不因为在函数执行期间有中断的调用而产生不同,也称中断安全。

2、不可重入函数的条件
如果函数满足以下条件,则属于不可重入函数:
1)调用了malloc或free。(因为malloc也是用全局链表来管理堆的)
2)调用了标准I/O库函数。(标准I/O库的很多实现都以不可重入的方式使用全局数据结构)
3)众所周知它们使用了静态数据结构体

3、可重入函数的条件
1)不为连续的调用持有静态数据。
2)不返回指向静态数据的指针;所有数据都由函数的调用者提供。
3)使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据。
4)绝不调用任何不可重入函数。

4、线程安全
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
线程安全问题都是由全局变量及静态变量引起的。
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

5、两者的区别与联系
可重入和线程安全是两个不同的概念:可重入函数一定是线程安全的;线程安全的函数可能是重入的,也可能是不重入的;线程不安全的函数一定是不可重入的。

可重入 => 线程安全

可重入函数要解决的问题是,不在函数内部使用静态或全局数据,不返回静态或全局数据,也不调用不可重入函数。
线程安全函数要解决的问题是,多个线程调用函数时访问资源冲突。

本文出自 “LOVEMERIGHT” 博客,请务必保留此出处http://lovemeright.blog.51cto.com/10808587/1826032
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: