14

Given the following:

public class CConsole {
  public static PrintWriter pw = new PrintWriter(System.out, true);
}

Is CConsole.pw.format("%d %d", x, y) thread-safe? That is, can multiple threads use this invocation and where is it described as being thread-safe. I don't see it in the PrintWriter class description nor the format() method description.

H2ONaCl
  • 10,644
  • 14
  • 70
  • 114
  • [This answer](http://stackoverflow.com/a/714424/1079354) may shed some light on it. – Makoto Jun 17 '12 at 15:00
  • 1
    possible duplicate of [Is a Java socket's PrintWriter thread safe?](http://stackoverflow.com/questions/714287/is-a-java-sockets-printwriter-thread-safe) – Stephen C Jun 17 '12 at 15:05
  • I did see that. It's not exactly the same question and there's no evidence given. – H2ONaCl Jun 17 '12 at 15:06
  • I disagree. It explains that PrintWriter is not *usefully* thread-safe. And if you want a proof, read the source code. – Stephen C Jun 17 '12 at 15:09
  • It also says PrintWriter is thread-safe without the qualification whereas another answer had the qualification. In my view this needs clarification. – H2ONaCl Jun 17 '12 at 15:16
  • [This](http://doc.sumy.ua/prog/Java/fclass/ch11_53.htm) says that _All of the methods of PrintWriter that write multiple times to the underlying output stream handle synchronization internally, so that PrintWriter objects are thread-safe._ – Kazekage Gaara Jun 17 '12 at 15:26
  • @KazekageGaara You might want to post this as the answer. – H2ONaCl Jun 17 '12 at 15:39

6 Answers6

14

This question does not have a simple answer...

The Writer, which is the superclass of PrintWriter explicitly mentions in its constructor documentation that all critical sections synchronize either on the Writer instance itself, or on an explicitly specified object. Therefore Writer is explicitly thread-safe...

Unfortunately, the PrintWriter subclass documentation makes no such promises explicitly. It inherits the Writer lock object, but there is no way to know whether any additional or overridden methods are still thread-safe.

On the other hand, as far as I can tell the Sun/OpenJDK PrintWriter implementation contains synchronized blocks in pretty much every method. But this does not seem to be explicitly documented behavior.

I'd rather play it safe and assume that PrintWriter is not thread-safe, than rely on undocumented behavior and regret this in the long run...

thkala
  • 84,049
  • 23
  • 157
  • 201
11

It's not exactly the same question and there's no evidence given.

It also says PrintWriter is thread-safe without the qualification whereas another answer had the qualification. In my view this needs clarification.

Since the OP doesn't understand (or maybe doesn't believe) the answers to the linked question, I will restate them.

  • The primary specification (i.e. the javadocs) do not state whether or not the class is thread-safe.

  • It is clear from reading the source code that it is thread-safe in the sense that all relevant operations are properly synchronized.

  • It is unlikely that Oracle would deliberately change the implementation to make it non-thread-safe ... in the sense above.

  • However, there are use-cases where a PrintWriter may not be completely thread-safe:

    • If a single PrinterWriter is used by multiple threads, the result can be unpredictable interleaving of output from the threads; e.g. if they use print rather than println.

    • If you have multiple PrintWriter objects wrapping the same underlying stream, there could be problems due to the PrintWriters internal use of a BufferedWriter.

    • Things may change if you subclass PrintWriter.

In summary, the current PrintWriter implementation (in the Oracle/OpenJDK codebase) is thread-safe, but you still need to be careful in some situations. There is also the possibility other 3rd-party Java implementations (i.e. not derived from the OpenJDK source tree) might not be thread-safe.

Thread-safety of applications that involve multiple threads writing to the same underlying stream is always nuanced ...


Note that the quote that @KazekageGaara found ...

"All of the methods of PrintWriter that write multiple times to the underlying output stream handle synchronization internally, so that PrintWriter objects are thread-safe."

... is from an O'Reilly text book - "Java Fundamental Classes Reference" by Mark Grand and Jonathan Knudsen. Since this is not an official Sun / Oracle publication, it is not in any way definitive.

Community
  • 1
  • 1
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
4

Yes, it's thread-safe. I can't understand why there are some folks telling it's not thread-safe. It definitely has the 'lock' member and its methods are fully synchronized under that lock object.

Some say PrintWriter.print method is not thread-safe but it's wrong. PrintWriter.print calls write(), which is definitely thread-safe. We all know that the write method is synchronized under 'lock'. So the print method is implicitly/naturally thread-safe.

PrintWriter.println shall be synchronized by itself, because it calls print() and println(), both of which are 'independently' thread-safe.

Eugene Chung
  • 352
  • 2
  • 10
2

Taken from here,in which a line says:

All of the methods of PrintWriter that write multiple times to the underlying output stream handle synchronization internally, so that PrintWriter objects are thread-safe.

Kazekage Gaara
  • 14,972
  • 14
  • 61
  • 108
  • The origin of this quote is "Java Fundamental Classes Reference" By Mark Grand and Jonathan Knudsen. It is an OReilly text book, not an official Sun / Oracle publication. Ergo, it is not definitive. – Stephen C Dec 04 '13 at 08:20
1
{ 
public void print(Object obj) 
     {

        write(String.valueOf(obj));
     }

     /* Methods that do terminate lines */

}

print is not synchronized...

So, if you are using print method, write ur own "My Writer" and synchronize it.

Or Else

if you use println()....Then it synchronized..

{

         public void println(Object x) {
         String s = String.valueOf(x);
         synchronized (lock) {
             print(s);
             println();
         }
     }

}
Daniel
  • 10,864
  • 22
  • 84
  • 115
Aneesh
  • 29
  • 1
  • 2
  • 7
0

No it is not really thread-safe.

See the write() methonds in PrintWriter.java here

They writes are synchronized on lock(defined here - which is the Writer object. If it were synchronized on this it would've been thread-safe but in this case it is not.

kjp
  • 3,086
  • 22
  • 30
  • what do you mean by not thread-safe? what it has to do with what lock is? – Amareswar May 21 '13 at 19:17
  • This is incorrect. The lock object belongs to the object, and synchronizing on it has an equivalent effect to synchronizing on `this` ... except that there is no interference from / with external synchronization on the PrintWriter. – Stephen C Mar 26 '18 at 00:36
  • @StephenC - No, I mean that if you have two PrintWriters on the same OutputStream you have there is no guarantee that they will not step on each other. So yes, in theory they are thread-safe, but not really. – kjp Mar 28 '18 at 22:06
  • I think you have that wrong. Assuming the PrintWriters were created using `new PrintWriter(OutputStream)`, the two PrintWriters will be synchronizing using the same lock object ... which is the `OutputStream`. They won't step on each other. Either way, you should spell out exactly what you mean ... in your answer. Also explain why synchronizing on `this` would solve the problem. – Stephen C Mar 28 '18 at 22:49
  • The lock is not the OutputStream, the lock is the Writer http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/io/PrintWriter.java#92 – kjp Mar 29 '18 at 17:35