Is writing to stdout using printf
thread-safe on Linux? What about using the lower-level write
command?
-
It's thread-safe; printf should be reentrant, and you won't cause any strangeness or corruption in your program.
You can't guarantee that your output from one thread won't start half way through the output from another thread. If you care about that you need to develop your own locked output code to prevent multiple access.
Martin Beckett : All calls to printf are likely to use the same buffer to build the string. Many implementations also share a buffer between scanf and printf - which can cause some weird debugging dependant bugs.Adam Hawes : I don't know what others do, but the GNU C library is thread-safe by default, so no it won't use the same buffer. -
They are both thread-safe to the point that your application won't crash if multiple threads call them on the same file descriptor. However, without some application-level locking, whatever is written could be interleaved.
-
It's not specified by the C standard -- it depends on your implementation of the C standard library. In fact, the C standard doesn't even mention threads at all, since certain systems (e.g. embedded systems) don't have multithreading.
In the GNU implementation (
glibc
), most of the higher-level functions in stdio that deal withFILE*
objects are thread-safe. The ones that aren't usually haveunlocked
in their names (e.g.getc_unlocked(3)
). However, the thread safety is at a per-function call level: if you make multiple calls toprintf(3)
, for example, each of those calls is guaranteed to output atomically, but other threads might print things out between your calls toprintf()
. If you want to ensure that a sequence of I/O calls gets output atomically, you can surround them with a pair offlockfile(3)/funlockfile(3)
calls to lock theFILE
handle. Note that these functions are reentrant, so you can safely callprintf()
in between them, and that won't result in deadlock even thoughtprintf()
itself makes a call toflockfile()
.The low-level I/O calls such as
write(2)
should be thread-safe, but I'm not 100% sure of that -write()
makes a system call into the kernel to perform I/O. How exactly this happens depends on what kernel you're using. It might be thesysenter
instruction, or theint
(interrupt) instruction on older systems. Once inside the kernel, it's up to the kernel to make sure that the I/O is thread-safe. In a test I just did with the Darwin Kernel Version 8.11.1,write(2)
appears to be thread-safe.DanM : Multi-threading is common in embedded systems.R.. : This answer is ignoring that the question was tagged unix/linux. POSIX requires stdio to be thread-safe, which is quite unfortunate since it kills performance and since there's no practical way to operate on the same FILE from multiple threads (data will come out hopelessly interleaved; atomicity is only at the character level). -
Whether you'd call it "thread-safe" depends on your definition of thread-safe. POSIX requires
stdio
functions to use locking, so your program will not crash, corrupt theFILE
object states, etc. if you useprintf
simultaneously from multiple threads. However, allstdio
operations are formally specified in terms of repeated calls tofgetc
andfputc
, so there is no larger-scale atomicity guaranteed. That is to say, if threads 1 and 2 try to print"Hello\n"
and"Goodbye\n"
at the same time, there's no guarantee that the output will be either"Hello\nGoodbye\n"
or"Goodbye\nHello\n"
. It could just as well be"HGelolodboy\ne\n"
. In practice, most implementations will acquire a single lock for the entire higher-level write call simply because it's more efficient, but your program should not assume so. There may be corner cases where this is not done; for instance an implementation could probably entirely omit locking on unbuffered streams.One way around this problem is the
flockfile
,ftrylockfile
, andfunlockfile
functions POSIX provides. These allow one particular thread to lock aFILE
for exclusive use, making it possible to achieve larger-than-single-char atomic writes.
0 comments:
Post a Comment