在学习Linux信号以后,我看到这样的一个代码。
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
int a = 0;
int b = 0;
void add()
{
a++;
sleep(5);
b++;
printf("a+b = %d\n",a+b);
}
void sigcb(int signo)
{
add();
}
int main()
{
signal(SIGINT,sigcb); //信号处理
add();
return 0;
}
对于以上代码,我们主观意识总是,先执行signal函数间接调用add函数,接着调用add函数。因此结果为2,4。结果真的是这样吗?
我们来看一下结果为啥会是3,4呢?
产生的原因: a++,与b++过程不是一次性完成。
多个执行流,同时进入一个函数执行功能 函数的重入
多个执行流竞争执行函数时,如果执行一个函数运行的结果不存在二义性,则称这个函数为可重入函数。
反之,如果一个函数在多个执行流中,结果存在二义性,则称函数为不可重入函数
判断基准
一个函数被多个执行流同时执行时,会不会产生数据二义性。
常见不可重入的情况:
- 调用malloc/free函数,malloc函数是使用全局链表进行管理堆资源的。
- 调用标准I/O函数
- 函数中使用静态成员或者全局变量。
常见可重入情况:
- 没有使用全局变量或者静态变量
- 不使用malloc/new开辟出空间的
- 不调用不可重入函数
- 不返回静态或者全局数据
重入于线程安全
- 函数是可重入的,则其为线程安全
- 如果函数是不可重入,则不能适用于多线程,容易产生线程安全问题
- 如果一个函数中使用全局变量,则该函数既不是线程安全的,也不是可重入的