一、C语言标准层面
-
C11以前的版本(C89/90, C99)不支持多线程,C语言也没有对这一块儿做出规定。也就是说语言层面并没有任何标准,那么具体是否线程安全依赖于操作系统&编译器。
-
而从C11开始,C语言支持多线程,从语言标准层面明确了printf是线程安全的。 C11 §7.21.2/7-8 states:
Each stream has an associated lock that is used to prevent data races when multiple threads of execution access a stream, and to restrict the interleaving of stream operations performed by multiple threads. Only one thread may hold this lock at a time. The lock is reentrant: a single thread may hold the lock multiple times at a given time. All functions that read, write, position, or query the position of a stream lock the stream before accessing it. They release the lock associated with the stream when the access is complete.
二、操作系统层面
-
POSIX标准规定stdio相关的操作API,除了函数名中包含有_unlocked的,否则都是原子的:
All functions that read, write, position, or query the position of a stream lock the stream before accessing it. They release the lock associated with the stream when the access is complete.
-
POSIX标准在推出后,得到了广泛的采纳。
UNIX 及其衍生版本:包括 Solaris、AIX、HP-UX、FreeBSD、OpenBSD、NetBSD 等
Linux:各种 Linux 发行版,如 Ubuntu、Debian、Fedora、Red Hat Enterprise Linux、SUSE Linux Enterprise 等
macOS:苹果公司的 macOS 操作系统遵循 POSIX 标准,并通过其基于 BSD 的内核提供了POSIX 兼容的文件系统。
Windows:微软的 Windows 操作系统通过 Cygwin 和 Windows Subsystem for Linux(WSL)等工具提供了对 POSIX 标准的支持。
所以如果你使用的操作系统遵循了POSIX标准,即使使用的是C11之前的版本,在使用printf时也不用担心线程安全问题。 但是要注意是否会有禁用io锁的情况,比如微软的MSVCRT,通常是线程安全的;但如果定义了特殊宏_CRT_DISABLE_PERFCRIT_LOCKS 或者使用了the _nolock-suffixed functions,就不是线程安全的。