似乎是glibc's implementation of fprintf() is thread-safe,但对于微软的CRT来说也是这样吗?
通过线程安全,我并不仅仅意味着崩溃,而且如果多个线程(在同一个进程中)调用fprintf()
,则文本将不会混合。
也就是说,例如,如果主题A调用fprintf(stdout, "aaaa");
而主题B调用fprintf(stdout, "bbbb");
,则保证不会混合成aabbaabb
。
有这样的保证吗?
答案 0 :(得分:10)
是。在多线程运行时库中,每个流都有一个关联的锁。这个锁是在对printf函数的任何调用开始时获取的,直到printf函数返回之前才会释放。
C11需要此行为(在C11之前,标准C中没有“线程”的概念)。 C11§7.21.2/ 7-8指出:
每个流都有一个关联的锁,用于防止多个数据争用 执行线程访问流,并限制由多个线程执行的流操作的交错。一次只有一个线程可以保持此锁定。锁是可重入的:单个线程可以在给定时间多次保持锁。
读取,写入,定位或查询流的位置的所有函数在访问流之前锁定流。当访问完成时,它们释放与流关联的锁。
Visual C ++并不完全支持C11,但它确实符合此要求。其他一些Visual C ++特定的注释:
只要您没有定义_CRT_DISABLE_PERFCRIT_LOCKS
(仅适用于静态链接的运行时库,libcmt.lib和朋友)或使用the _nolock-suffixed functions,那么单个流上的大多数操作都是原子的
如果您在流上的多个操作中需要原子性,则可以通过使用_lock_file
和_unlock_file
自行获取和释放流锁来自行获取文件锁。