# 12.7.3 在线程化的程序中使用已存在的库函数
大多数 Linux 函数,包括定义在标准 C 库中的函数(例如 malloc、free、realloc、printf 和 scanf)都是线程安全的,只有一小部分是例外。图 12-41 列出了常见的例外。(参考 [110] 可以得到一个完整的列表。)strtok 函数是一个已弃用的(不推荐使用)函数。asctime、ctime 和 localtime 函数是在不同时间和数据格式间相互来回转换时经常使用的函数。gethostbyname、gethostbyaddr 和 inet_ntoa 函数是已弃用的网络编程函数,已经分别被可重入的 getaddrinfo、getnameinfo 和 inet_ntop 函数取代(见第 11 章)。除了 rand 和 strtok 以外,所有这些线程不安全函数都是第 3 类的,它们返回一个指向静态变量的指针。如果我们需要在一个线程化的程序中调用这些函数中的某一个,对调用者来说最不惹麻烦的方法是加锁-复制。然而,加锁-复制方法有许多缺点。首先,额外的同步降低了程序的速度。第二,像 gethostbyname 这样的函数返回指向复杂结构的结构的指针,要复制整个结构层次,需要深层复制 (deep copy) 结构。第三,加锁-复制方法对像 rand 这样依赖跨越调用的静态状态的第 2 类函数并不有效。
| 线程不安全函数 | 线程不安全类 | Linux 线程安全版本 |
|---|---|---|
rand | 2 | rand_r |
strtok | 2 | strtok_r |
asctime | 3 | asctime_r |
ctime | 3 | ctime_r |
gethostbyaddr | 3 | gethostbyaddr_r |
gethostbyname | 3 | gethostbyname_r |
inet_ntoa | 3 | (无) |
localtime | 3 | localtime_r |
图 12-41 常见的线程不安全的库函数
因此,Linux 系统提供大多数线程不安全函数的可重入版本。可重入版本的名字总是以“_r”后缀结尾。例如,asctime 的可重入版本就叫做 asctime_r。我们建议尽可能地使用这些函数。
← 12.7.2 可重入性 12.7.4 竞争 →