80

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
Raedwald
  • 46,613
  • 43
  • 151
  • 237
Ellen Spertus
  • 6,576
  • 9
  • 50
  • 101
  • Always the first. But read @John Vint's answer, because you probably don't want strings to be spewed all over the console. – parkovski Feb 27 '12 at 03: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 Mar 09 '12 at 00: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 Sep 22 '14 at 15:19
  • Very interesting, @mucaho. Would you be willing to post a program and transcript as an answer? – Ellen Spertus Sep 23 '14 at 00: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](https://github.com/mucaho/jnetrobust/blob/master/jnetrobust-core/src/test/java/net/ddns/mucaho/jnetrobust/DelayedTest.java). Make sure to set the `DEBUG` flag to true in the first few lines. – mucaho Sep 23 '14 at 13:11
  • Yes output mixes with multiple threads – SMUsamaShah Feb 03 '15 at 15:11

4 Answers4

75

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.

maerics
  • 151,642
  • 46
  • 269
  • 291
  • 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. – Gerrit Brink Sep 26 '13 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 Feb 22 '14 at 21:19
  • How does one explain that the implementation of `println` actually [does the very thing you describe](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/io/PrintStream.java?av=f#804) here? Doesn't that make it thread-safe in the same vein as your solution? – Makoto Sep 27 '14 at 21:40
  • 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 Sep 28 '14 at 16:27
  • 8
    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 Oct 01 '15 at 15:31
  • @Holger: yes my code sample is obviously an illustration and not intended as a real-world solution. I'll update the answer to say as much. – maerics Oct 01 '15 at 19:49
  • @maerics - please mention some factors to consider before choosing your implementation of a thread safe println. – MasterJoe Jul 12 '17 at 23:38
  • @Holger - "You are only thread safe when......on the same object." Please explain this. What is resource here ? – MasterJoe Jul 12 '17 at 23:50
  • 1
    @testerjoe2: “resource” is whatever you want to access in a thread safe manner, here, it’s the console (or stout). There is nothing more to explain, `synchronized` establishes mutual exclusion and thread safety between threads using it with the same object. That’s what it does. – Holger Jul 13 '17 at 06:08
  • @Holger - Newbie here. Is the above code not thread safe only because it reads the System.out variable twice (so its possible that someone can call System.setOut(…) right between these two reads) ? – MasterJoe Jul 13 '17 at 06:24
  • 3
    @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 Jul 13 '17 at 06:49
  • @Holger - Thanks again ! Trying to understand "without synchronized (System.out)" --- Some JVMs might not implement a println which is synchronized on System.out. When we use the answer code, other threads can access system.out. So, unless println is declared as a synchronized method, you can't guarantee the thread safety of system.out. Did I get that right ? – MasterJoe Jul 13 '17 at 21:54
27

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

twimo
  • 4,061
  • 5
  • 29
  • 32
  • 7
    Thank you, although I wanted to know if the interface guaranteed synchronization, not whether current implementations (which might be replaced) provided synchronization. – Ellen Spertus May 06 '12 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 May 07 '12 at 02: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 Nov 06 '13 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.

Erik
  • 4,305
  • 3
  • 36
  • 54
John Vint
  • 39,695
  • 7
  • 78
  • 108
  • thanks for the answer, but I think you misunderstood my question. I have tried making it clearer. – Ellen Spertus Feb 27 '12 at 03:41
  • Yea I did answer that at the bottom I could have made it more clear. – John Vint Feb 27 '12 at 03:42
  • 1
    Is there some documentation somewhere that leads you to believe that there is a lock acquired on the OutputStream instance? – maerics Feb 27 '12 at 04:34
  • It isn't documented. I am speaking merely on a matter of fact. – John Vint Feb 27 '12 at 04:45
  • 2
    Could you clarify how you know a lock is acquired on OutputStream? – Ellen Spertus Feb 27 '12 at 05: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 Feb 27 '12 at 05: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 Feb 27 '12 at 05:36
  • 1
    I have looked at the source it is synchronized. There are also papers on the fact PrintStream is thread-safe. If the OP does not want to use it becauses its not documented to be thread safe that is on him. I am simply stating it is thread safe – John Vint Feb 27 '12 at 13:13
  • 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.) :-) – Ellen Spertus Feb 27 '12 at 23:49
  • @StephenC, actually, even looking at the source code isn't enough. It has to be part of the API before we can assume it to be true on all implementations. – Ellen Spertus Feb 27 '12 at 23:50
  • @espertus - actually, you misunderstood my comment. It should be read in the context of the previous comment; i.e. it is implicitly about characterizing a *specific* JVM implementation. – Stephen C Feb 28 '12 at 00:26
  • 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 Feb 28 '12 at 00:40
  • @espertus No problem - it's a good question - I overlooked the lack of specification in Java's API. – John Vint Feb 28 '12 at 02: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
parkovski
  • 1,503
  • 10
  • 13
  • 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 Feb 27 '12 at 04:06
  • @parkovski, thanks for your answer, but could you explain why you know the output won't be interleaved? – Ellen Spertus Feb 27 '12 at 05:11