可重入函数(Reentrant Function)和非可重入函数(Non-Reentrant Function)的区别,是并发编程中的基础知识,尤其跟多线程 / 信号处理 / 中断安全密切相关。
✅ 一句话理解:
可重入函数可以被多个线程或中断安全地同时调用;
非可重入函数一旦中途被打断再次调用,可能导致数据错乱或崩溃。
✅ 可重入函数的定义:
一个函数是可重入的,当它可以在执行过程中被中断,并且之后可以安全地重新进入执行,而不会导致任何错误。
换句话说,它可以“同时在多个上下文中执行”。
✅ 可重入函数必须满足什么条件?
- ❌ 不使用全局变量或静态变量(或者对它们加锁保护)
- ✅ 不调用非可重入函数(比如 malloc、printf 等)
- ✅ 不依赖共享资源(或者访问时加锁)
- ✅ 不修改自身的数据段
- ✅ 只操作栈上的局部变量或参数
✅ 非可重入函数的常见特征:
- 内部使用静态变量保存状态
- 修改全局状态或资源
- 没有线程同步机制
- 依赖不可重入的函数(如
strtok()
)
✅ 举例对比
✅ 可重入函数示例:strlen()
size_t strlen(const char* s) {
size_t len = 0;
while (*s++) ++len;
return len;
}
- 不用全局变量
- 不依赖外部资源
- 操作仅限于参数 → ✔️ 可重入
❌ 非可重入函数示例:strtok()
char* strtok(char* str, const char* delim);
- 内部使用 静态指针 记住上次调用的位置
- 多线程 / 中断时调用会打乱状态 → ❌ 非可重入
✅ 替代方案:使用 strtok_r()
(线程安全 + 可重入)
✅ 可重入函数 vs 线程安全函数
特性 | 可重入函数 | 线程安全函数 |
---|---|---|
能否中断再调用 | ✅ 可以 | ❌ 不保证 |
是否可多线程调用 | ✅ | ✅ |
是否共享全局状态 | ❌ 不共享 | 可能共享(但有保护) |
示例 | strlen() | strtok_r() |
👉 可重入函数 ⊂ 线程安全函数
✅ 常见非可重入函数列表(面试问得多)
函数名 | 问题原因 |
---|---|
strtok() | 静态变量保存状态 |
asctime() | 静态缓冲区 |
localtime() | 静态结构返回 |
rand() | 静态种子 |
gethostbyname() | 静态数据结构 |
✅ 总结一句话:
可重入函数:无副作用、无全局变量、只用局部变量、不中断有错。
可用于中断处理、信号处理、多线程安全场景,是高并发系统中的基本单元。