81

If multiple threads call System.out.println(String) without synchronization, can the output get interleaved? Or is the write of each line atomic? The API makes no mention of synchronization, so this seems possible, or is interleaved output prevented by buffering and/or the VM memory model, etc.?

EDIT:

For example, if each thread contains:

System.out.println("ABC");

is the output guaranteed to be:

ABC
ABC

or could it be:

AABC
BC
6
  • Always the first. But read @John Vint's answer, because you probably don't want strings to be spewed all over the console.
    – parkovski
    Commented Feb 27, 2012 at 3:51
  • 4
    Keep in mind that even if both System.out.println and System.err.println are synchronized, these two aren't synchronized between themselves so System.err.println may interleave with System.out.println giving you console that may not be what you expect.
    – Pacerier
    Commented Mar 9, 2012 at 0:16
  • 1
    Actually I quite often receive interleaved output (your demonstrated case 2), both in IntelliJ Idea and Eclipse, despite what other people are telling you (jdk 1.6).
    – mucaho
    Commented Sep 22, 2014 at 15:19
  • Very interesting, @mucaho. Would you be willing to post a program and transcript as an answer? Commented Sep 23, 2014 at 0:13
  • @espertus Unfortunately I am not able to extract a small sample program to demonstrate it, but I can link you to a test case which shows interleaved output when run. Look for empty lines, the line above will be interleaved most certainly. run JNetRobust.DelayedTest. Make sure to set the DEBUG flag to true in the first few lines.
    – mucaho
    Commented Sep 23, 2014 at 13:11

4 Answers 4

76

Since the API documentation makes no mention of thread safety on the System.out object nor does the PrintStream#println(String) method you cannot assume that it is thread-safe.

However, it is entirely possible that the underlying implementation of a particular JVM uses a thread-safe function for the println method (e.g. printf on glibc) so that, in reality, the output will be guaranteed per your first example (always ABC\n then ABC\n, never interspersed characters per your second example). But keep in mind that there are lots of JVM implementations and they are only required to adhere to the JVM specification, not any conventions outside of that spec.

If you absolutely must ensure that no println calls will intersperse as you describe then you must enforce mutual exclusion manually, for example:

public void safePrintln(String s) {
  synchronized (System.out) {
    System.out.println(s);
  }
}

Of course, this example is only an illustration and should not be taken as a "solution"; there are many other factors to consider. For example, the safePrintln(...) method above is only safe if all code uses that method and nothing calls System.out.println(...) directly.

12
  • 1
    Dunno about the downvote, but it seems that the standard implementation for print etc calls the write method on the PrintStream which is already wrapped in a synchronized block. Thus it would not be possible to print out jibberish via mixing up the characters in the out, it is just the order in which the strings are printed which may be affected. Commented Sep 26, 2013 at 14:20
  • 4
    @Grep: sure, I'm just being pedantic about the difference between the documented interface (which makes no promise of synchronization) vs common implementations (which likely are synchronized).
    – maerics
    Commented Feb 22, 2014 at 21:19
  • 7
    @Makoto when you say "the implementation of println" you are talking about the implementation of a single JVM, not all JVMs. Just because one JVM chose to make that method thread safe it does not mean all JVMs do - the specification does not require it.
    – maerics
    Commented Sep 28, 2014 at 16:27
  • 10
    The safePrintln isn’t safer than a simple print statement. Just because you are synchronizing on a particular object, you are not getting any safety. You are only thread safe when all code accessing the resource is synchronizing on the same object. But assuming that all code calling print methods is synchronizing on the System.out instance is bringing you back to where you have started. Further, your code is broken as it reads the System.out variable twice. If someone calls System.setOut(…) right between these two reads, you synchronization breaks.
    – Holger
    Commented Oct 1, 2015 at 15:31
  • 4
    @testerjoe2: That’s one possible race condition. The other point is that another thread could just call System.out.println(s); without synchronized (System.out), so this method only works if all threads adhere to the convention to use this method (or are doing synchronized on their own) instead of accessing System.out directly and that no-one is calling setOut. That’s why synchronization is usually combined with encapsulation, not allowing direct access to the resource.
    – Holger
    Commented Jul 13, 2017 at 6:49
28

The OpenJDK source code answers your question:

public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

Reference: http://hg.openjdk.java.net/jdk6/jdk6/jdk/file/39e8fe7a0af1/src/share/classes/java/io/PrintStream.java

3
  • 7
    Thank you, although I wanted to know if the interface guaranteed synchronization, not whether current implementations (which might be replaced) provided synchronization. Commented May 6, 2012 at 21:16
  • 2
    Then the declaration of println() without the "synchronized" keyword has made it clear that it doesn't guarantee synchronization. The implementation further proves it.
    – twimo
    Commented May 7, 2012 at 2:39
  • 3
    I have downvoted because you infer the specification (i.e. behaviour of other implementations) from the concrete implementation even after the it was reminded to you that you cannot do that. Your implementation actually proves that sync keyword is not necessary in the declaration to achieve the synchronization guarantee. So, everything you claim is completely against the logic and your own example.
    – Val
    Commented Nov 6, 2013 at 15:03
15

As long as you don't change the OutputStream via System.setOut it is thread safe.

Though it is thread safe you can have many threads writing to System.out such that

Thread-1
  System.out.println("A");
  System.out.println("B");
  System.out.println("C");
Thread-2
  System.out.println("1");
  System.out.println("2");
  System.out.println("3");

can read

1
2
A
3
B
C

among other combinations.

So to answer your question:

When you write to System.out – it acquires a lock on the OutputStream instance - it will then write to the buffer and immediately flush.

Once it releases the lock, the OutputStream is flushed and written to. There would not be an instance where you would have different strings joined like 1A 2B.

Edit to answer your edit:

That would not happen with System.out.println. Since the PrintStream synchronizes the entire function, it will fill the buffer and then flush it atomically. Any new thread coming in will now have a fresh buffer to work with.

13
  • 2
    Could you clarify how you know a lock is acquired on OutputStream? Commented Feb 27, 2012 at 5:09
  • 4
    @JohnVint: not trying to pick a fight here, but if it's not documented then the best you can do is say that some particular JVM implementation is, in fact, thread safe. In general you are probably right but there's no guarantee of this behavior on every compliant JVM, per the JLS or Java API.
    – maerics
    Commented Feb 27, 2012 at 5:15
  • 4
    And you can only say that with total confidence if you've actually looked at the source code and seen that it actually does synchronize properly.
    – Stephen C
    Commented Feb 27, 2012 at 5:36
  • 2
    My reason for wanting to know is that I am a professor teaching about Java synchronization and want my students to understand what can and can't go wrong if they fail to explicitly use synchronization mechanisms. I'd like to be able to give them a reference for whatever I claim, not just that someone online asserted it. (I don't let my students cite Wikipedia.) I mean no disrespect to @JohnVint. I'd react the same to anyone not JamesGosling, GuySteele, or JoshBloch. (I don't think John Vint can take offense at my not knowing him when he didn't know I was a she, not a he.) :-) Commented Feb 27, 2012 at 23:49
  • 2
    @espertus My apologies about the 'him' comment! I think maerics brings up a good point regarding documentation. It is true the underlying implementation can change and not violate the contract. If Oracle decides to do that it would be at the cost of losing all Java developers :) That being said, if you were to run you program you will not see any interleaved strings. If you want to ensure complete thread-safety and document it you can extend PrintStream and override each method with synchronized
    – John Vint
    Commented Feb 28, 2012 at 0:40
3

Just to clarify, say you have two threads, one that prints "ABC" and another that prints "DEF". You will never get output like this: ADBECF, but you could get either

ABC
DEF 

or

DEF
ABC
2
  • That would only happen with print, not println. Println will atomically print then write a new line. So you would have ABC above DEF or DEF above ABC
    – John Vint
    Commented Feb 27, 2012 at 4:06
  • @parkovski, thanks for your answer, but could you explain why you know the output won't be interleaved? Commented Feb 27, 2012 at 5:11

Not the answer you're looking for? Browse other questions tagged or ask your own question.