8

It seems that glibc's implementation of fprintf() is thread-safe, but is that so for Microsoft's CRT, as well?

By thread-safe, I don't mean just crashing, but also that if multiple threads (in the same process) call fprintf(), the texts will not be mixed.

That is, for example, if thread A calls fprintf(stdout, "aaaa"); and thread B calls fprintf(stdout, "bbbb"); it's guaranteed not to mix to become aabbaabb.

Is there such a guarantee?

Community
  • 1
  • 1
sashoalm
  • 75,001
  • 122
  • 434
  • 781
  • Strange: text still seems to be mixed: https://github.com/git/git/commit/116d1fa6c693e13321dc4c6abe256ca7878e55a5 – VonC Dec 05 '19 at 20:04

1 Answers1

14

Yes. In the multithreaded runtime libraries, every stream has an associated lock. This lock is acquired at the beginning of any call to a printf function and not released until just before that printf function returns.

This behavior is required by C11 (there was no concept of "threads" in standard C until C11). 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.

Visual C++ does not fully support C11, but it does conform to this requirement. A couple of other Visual C++-specific comments:

As long as you are not defining _CRT_DISABLE_PERFCRIT_LOCKS (which only works with the statically-linked runtime libraries, libcmt.lib and friends) or using the _nolock-suffixed functions, then most operations on a single stream are atomic.

If you require atomicity across multiple operations on a stream, you can acquire the lock for a file yourself by acquiring and releasing the stream lock yourself using _lock_file and _unlock_file.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • How far back does this go? For example, was `fprintf()` thread-safe in VC6's multithreaded CRT? – sashoalm Mar 21 '14 at 09:36
  • Yes, this is the case in the VC6 multithreaded runtime libraries. VC6 is the oldest version of the sources that I have readily available; I'm not entirely sure when this was implemented. – James McNellis Mar 21 '14 at 16:26
  • @JamesMcNellis You state "Yes. In the multithreaded runtime libraries, every stream has an associated lock." How do I know if the library I am using is a multithreaded runtime library? – Trisped Feb 11 '16 at 19:58
  • 1
    @Trisped All of the runtime libraries are multithreaded since Visual Studio 2005. See https://support.microsoft.com/en-us/kb/154753 for details about past versions. – James McNellis Feb 13 '16 at 01:42
  • 1
    Any link to MSDN to support this? This page doesn't say anything about thread safety and interleaving of the output: https://msdn.microsoft.com/en-us/library/xkh07fe2.aspx – Serge Rogatch Aug 30 '16 at 10:08