可重入函数与线程安全的区别与联系
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
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
相关文章推荐
- 排序算法总结
- jenkins和docker 在docker里运行jenkins
- SAP Function ALV 01(样式、排序、筛选、事件)
- 第十三讲:软考中高项13_战略管理、业务流程管理、知识管理
- 做到这些你才算的上是真正牛逼的电商运营
- LightOJ1370 Bi-shoe and Phi-shoe 欧拉函数筛法
- 剑指offer系列-T22栈的压入、弹出序列
- int main(int argc, char* argv[])用法解析
- linux系统调用:exit()与_exit()函数详解
- 安卓非微信内置浏览器中的网页调起微信支付的方案研究
- 日本UX站点Uxmilk.jp对Mockplus的介绍 - 简洁快速的原型图设计工具Mockplus使用指南
- 大型网站架构演变和知识体系
- Android Data Binding 系列(二) -- Binding与Observer实现
- PropertyPlaceholderConfigurer加载属性配置文件:
- 第十二讲:软考中高项12_外包管理、需求管理、组织级与大项目管理
- json eval函数解析
- 七年电商路,九条运营心经!
- 查看http的并发请求数及其TCP连接状态
- 自学swift (2) ---修饰符(后续补充中)
- C++ std::size_t