本文共 1113 字,大约阅读时间需要 3 分钟。
为了理解可重入函数的概念,我们先来看这样一个例子:
main函数调用insert函数向链表中头插节点node1,插入操作分为两步。
假设它刚做完第一步的时候。由于硬件中断使进程切换到内核。再次回用户态之前检查到有信号待处理,于是切换到sighandler函数,sighandler也调用insert函数向同一个链表中头插节点node2。
把插入操作的两步都做完之后从sighandler返回内核态,再次回到用户态从main函数调用的insert函数中继续执⾏第⼆步。
结果是:main函数和sighandler先后向链表中插入两个节点,而最后只有一个节点node1插入链表中:
像这样,两个执行流main和sighandler同时访问insert函数,就会导致结点丢失。类似于insert这种情况的函数就叫做不可重入函数
这里的重入是指:同一时刻一个函数被多个执行流调用相对的,有可重入函数:只访问自己私有栈的变量和参数。这个例子同样说明:没有线程,一个进程里也会有多个执行流,比如信号的捕捉。
所以,我们可以总结出可称为不可重入函数的3个条件:
1.调用了malloc或free,因为malloc也是用全局链表来管理堆的。
2.调⽤了标准I/O库函数。标准I/O库的很多实现都以不可重入的方式使⽤全局数据结构。 3.必须以线程安全的方式实现的系统函数。从第3条我们可以看出,可重入/不可重入函数与一个概念相关,这就是线程安全。
首先,我们需要明确线程安全的概念:一个线程对全局变量这种具有全局性的东西的操作影响到别的线程。简单来说,只要一个程序/进程的线程之间没有涉及到对全局变量的操作,那么这个程序/进程就是线程安全的。
这样看来,线程安全和可重入函数貌似是一样的。后者也是只访问自己私有栈的变量和参数,没有访问全局变量。
其实,可重入函数与线程安全并不相同,一般来说,可重入的函数一定是线程安全的,但反过来就不一定成立了。
前方高能:一大段文字即将来袭。。。
总结:可重入函数与线程安全的区别与联系
1.线程安全是在多个线程情况下引发的,而可重入函数在只有一个线程的情况下也可以有。
2.线程安全不一定是可重入的,而可重入函数则一定是线程安全的。 3.如果一个函数中有全局变量,那么这个函数既不是线程安全也不是可重入的。 4.如果在某函数中将对临界资源的访问加上锁,则这个函数是线程安全的。 5.线程安全函数能够使不同的线程访问同一块地址空间,而可重入函数要求不同的执行流对数据操作互不影响。 6.可重入函数是线程安全函数的一种,其特点在于它们被多个线程调用时,不会引用任何共享数据。