【问题标题】:Is MSVCRT's implementation of fprintf() thread safe?MSVCRT 的 fprintf() 线程实现是否安全?
【发布时间】:2014-04-27 16:05:46
【问题描述】:

好像glibc's implementation of fprintf() is thread-safe,但微软的CRT也是这样吗?

我所说的线程安全,并不是说只是崩溃,而是如果多个线程(在同一个进程中)调用fprintf(),文本不会混合。

也就是说,比如线程A调用fprintf(stdout, "aaaa");,线程B调用fprintf(stdout, "bbbb");,保证不会混成aabbaabb

有这样的保证吗?

【问题讨论】:

标签: c multithreading printf msvcrt


【解决方案1】:

是的。在多线程运行时库中,每个流都有一个关联的锁。这个锁是在任何调用 printf 函数开始时获取的,直到 printf 函数返回之前才释放。

C11 需要这种行为(在 C11 之前的标准 C 中没有“线程”的概念)。 C11 §7.21.2/7-8 规定:

每个流都有一个关联的锁,用于防止多个流发生数据竞争 执行线程访问流,并限制由多个线程执行的流操作的交错。一次只能有一个线程持有这个锁。锁是可重入的:单个线程可以在给定时间多次持有锁。

所有读取、写入、定位或查询流位置的函数都会在访问流之前锁定该流。当访问完成时,它们会释放与流关联的锁。

Visual C++ 并不完全支持 C11,但它确实符合这个要求。其他几个 Visual C++ 特定的 cmets:

只要您不定义_CRT_DISABLE_PERFCRIT_LOCKS(仅适用于静态链接的运行时库、libcmt.lib 和朋友)或使用the _nolock-suffixed functions,那么单个流上的大多数操作都是原子的。

如果您需要跨流的多个操作的原子性,您可以通过使用_lock_file_unlock_file 自己获取和释放流锁来自己获取文件的锁。

【讨论】:

  • 这可以追溯到多远?例如,fprintf() 在 VC6 的多线程 CRT 中是线程安全的吗?
  • 是的,在 VC6 多线程运行时库中就是这种情况。 VC6 是我现有的最旧版本的源代码;我不完全确定这是什么时候实施的。
  • @JamesMcNellis 您说“是的。在多线程运行时库中,每个流都有一个关联的锁。”如何知道我使用的库是否为多线程运行时库?
  • @Trisped 自 Visual Studio 2005 以来,所有运行时库都是多线程的。有关过去版本的详细信息,请参阅 support.microsoft.com/en-us/kb/154753
  • 有任何指向 MSDN 的链接来支持这一点吗?此页面没有说明线程安全和输出交错:msdn.microsoft.com/en-us/library/xkh07fe2.aspx
猜你喜欢
  • 1970-01-01
  • 2018-06-04
  • 1970-01-01
  • 2012-05-20
  • 1970-01-01
  • 1970-01-01
  • 2010-10-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多