文章标题

来源:互联网 发布:centos开机自启动 编辑:程序博客网 时间:2024/06/06 07:51

一、概念:
1、**可重入函数
1)、函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数,这称为重入。
2)、insert函数访问一个全局链表,有可能因为重入而造成错乱,像这样的函数称为不可重入函数。如果一个函数符合以下条件之一则是不可重入的:
a、调用了malloc/free,因为malloc也是用全局链表来管理堆的;
b、调用了标准I/O库函数。标准I/O库的很多实现都以不可重入的方式使用全局数据结构;
c、可重入体内使用了静态的数据结构;
3)、相对应的,当一个执行流因为异常或者被内核切换而中断正在执行的函数而转化为另外一个执行流时,当后者的执行流对同一个函数的操作并不影响前一个执行流恢复后执行函数产生的结果,我们就称这个函数为可重入函数。可重入函数只访问自己的局部变量或参数。
总结——一个可重入函数可以被多个执行流重复进入,内部使用的数据都应该来自自身的栈空间,包括返回值也不应该是全局或者静态的,可以允许有该函数的多个副本在运行,而正是因为其中的操作数据都来自于自身的栈空间,而每次调用函数会开辟不同的栈空间,因此二者互不影响。
4)、可重入函数的分类
a、显式可重入函数——所有函数的参数都是值传递的(没有指针),并且所有的数据引用都是本地的自动栈变量(即没有引用静态或全局变量),则函数是显式可重入的,也就是说不管如何调用,我们都可断言它是可重入的。
b、隐式可重入函数——可重入函数中的一些参数是引用传递(使用了指针),也就是说,在调用线程小心地传递指向非共享数据的指针时,它才是可重入的。
可重入函数可以有多余一个任务并发使用,而不必担心数据错误,相反,不可重入函数不能有由超过一个任务所共享,除非能确保函数的互斥(或者使用信号量,或者在代码的关键部分禁用中断)。可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据,可重入函数要么使用本地变量,要么在使用全局变量时保护自己的数据。
5)、一个可重入函数需要满足的是:
a、不使用全局变量或静态变量
b、不使用用malloc或new 开辟出的空间
c、不调用不可重入函数
d、不返回静态或全局数据,所有数据都由函数的调用提供
e、使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据
总结: 可重入函数主要用于多任务环境中,一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误;而不可重入函数由于使用了一些系统资源,比如全局变量区,中断向量表等,所以它如果被中断的话,可能会出现问题,这类函数是不能运行在多任务环境下的。
2、*线程安全
一个函数被称为线程安全的(thread-safe),当且仅当被多个并发进程反复调用时,它会一直产生正确的结果。反之,如果一个函数不是线程安全的,我们就说它是线程不安全的(thread-unsafe).
所以,有四类函数称为线程不安全的:
1)、不保护共享变量的函数;
2)、函数状态随着调用改变的函数;
3)、返回指向静态变量指针的函数;
4)、调用线程不安全函数的函数;
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。或者说一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,即不用考虑同步的问题。
线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。根据线程的同步与互斥,也就是当俩个线程同时访问到同一个临界资源的时候,如果对临界资源的操作不是原子的就会产生冲突,使得结果并不如最终预期的那样。因此,线程安全是指多个线程访问同一个区域的时候其最终的结构是可预期的,并不会因为产生冲突或者异常中断再次恢复而使结果不可预期。
二、可重入函数与线程安全的区别与联系
函数可以是可重入的,也可以是线程安全的,或者两者皆是,或者两者皆非。不可重入函数不能由多个线程使用。
1、线程安全是在多线程情况下引发的,而可重入函数可以在只有一个线程的情况下发生。
2、线程安全不一定是可重入的,而可重入函数则一定是线程安全的。
3、如果一个函数有全局变量,则这个函数既不是线程安全的也不是可重入的 。
4、如果一个函数当中的数据全是自身栈空间的,则这个函数既是线程安全的也是可重入的。
5、如果将对临界资源的访问加锁,则这个函数是线程安全的;但如果重入函数的话加锁还未释放,则会产生死锁,因此不能重入。
6、线程安全函数能够使不同的线程访问同一块地址空间,而可重入函数要求不同的执行流对数据的操作不影响结果,使结果是相同的。

0 0
原创粉丝点击