在Linux中,重入性指的是一个函数可以安全地在同时被多个线程或进程调用时正确地执行。不可重入性则表示一个函数在被并发调用时可能会导致不确定的行为或数据损坏。
不可重入
以下是一些示例:
- 静态变量:当函数使用静态变量时,可能会导致不可重入性。因为静态变量是在函数的整个生命周期内存在的,如果多个线程同时调用该函数,它们可能会修改或读取同一个静态变量,从而导致数据竞争和不一致的结果。
int not_reentrant()
{
static int counter = 0;
counter++;
return counter;
}
- 全局变量:与静态变量类似,全局变量也可能导致不可重入性。多个线程同时访问全局变量时可能会引发竞争条件和数据不一致的问题。
int global_var = 0;
int not_reentrant()
{
global_var++;
return global_var;
}
- 动态内存分配:当函数在堆上分配内存并返回指向该内存的指针时,如果多个线程同时调用该函数,它们可能会分配相同的内存地址,导致内存泄漏或访问冲突。
char* not_reentrant()
{
char* buffer = malloc(sizeof(char) * 100);
return buffer;
}
- 使用全局或静态缓冲区:如果函数使用全局或静态缓冲区来存储中间结果,而多个线程同时调用该函数,并且函数会在缓冲区上进行写操作,可能会导致数据竞争和不可预测的结果。
char global_buffer[100];
char* not_reentrant()
{
return global_buffer;
}
可重入
- 不使用全局变量或静态变量
- 不使用用malloc或者new开辟出的空间
- 不调用不可重入函数
- 不返回静态或全局数据,所有数据都有函数的调用者提供
- 使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据
可重入与线程安全联系
- 函数是可重入的,那就是线程安全的
- 函数是不可重入的,那就不能由多个线程使用,有可能引发线程安全问题
- 如果一个函数中有全局变量,那么这个函数既不是线程安全也不是可重入的。
他们的区别
- 可重入函数是线程安全函数的一种
- 线程安全不一定是可重入的,而可重入函数则一定是线程安全的。
- 如果将对临界资源的访问加上锁,则这个函数是线程安全的,但如果这个重入函数若锁还未释放则会产生死锁,因此是不可重入的。