PrintWriter是线程安全的吗?

时间:2012-06-17 14:58:31

标签: java printwriter

鉴于以下内容:

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

CConsole.pw.format("%d %d", x, y)线程安全吗?也就是说,多个线程可以使用此调用吗?它被描述为线程安全的位置。我在PrintWriter类描述和format()方法描述中都没有看到它。

6 个答案:

答案 0 :(得分:10)

这个问题没有一个简单的答案......

Writer,它是PrintWriter的超类,在其构造函数文档中明确提到所有关键部分在Writer实例本身或显式指定的对象上同步。因此Writer显然是线程安全的......

不幸的是,PrintWriter子类文档没有明确地提出这样的承诺。它继承了Writer锁定对象,但是无法知道任何其他或重写的方法是否仍然是线程安全的。

另一方面,据我所知,Sun/OpenJDK PrintWriter implementation包含synchronized几乎所有方法中的块。 但是这似乎不是明确记录的行为。

我宁愿安全地玩它并假设PrintWriter不是线程安全的,而不是依赖于未记录的行为并且从长远来看后悔......

答案 1 :(得分:8)

  

这不是完全相同的问题,并且没有给出任何证据。

     

它还说PrintWriter是没有资格的线程安全的,而另一个答案有资格。在我看来,这需要澄清。

由于OP不理解(或者可能不相信)链接问题的答案,我将重申它们。

  • 主要规范(即javadocs)不说明该类是否是线程安全的。

  • 从阅读源代码可以清楚地看出,在所有相关操作都已正确同步的意义上,它是线程安全的。

  • 在上述意义上,Oracle不太可能故意改变实现以使其成为非线程安全的。

  • 但是,有些用例PrintWriter可能不完全是线程安全的:

    • 如果多个线程使用单个PrinterWriter,则结果可能是线程输出的不可预测的交错;例如如果他们使用print而不是println。

    • 如果您有多个PrintWriter个对象包装相同的基础流,可能会因PrintWriter内部使用BufferedWriter而导致问题。

      < / LI>
    • 如果您继承PrintWriter,事情可能会发生变化。

总之,当前PrintWriter实现(在Oracle / OpenJDK代码库中)是线程安全的,但在某些情况下仍需要小心。其他第三方Java实现(即不是从OpenJDK源代码树派生)也可能不是线程安全的。

涉及多个线程写入同一底层流的应用程序的线程安全始终是细微的...


请注意@KazekageGaara发现的引用......

  

多次写入基础输出流的PrintWriter的所有方法都在内部处理同步,因此PrintWriter个对象是线程安全的。”

...来自Mark Grand和Jonathan Knudsen的O'Reilly教科书 - “Java Fundamental Classes Reference”。由于这不是正式的Sun / Oracle出版物,因此它绝不是最终的。

答案 2 :(得分:2)

是的,它是线程安全的。我不明白为什么有些人告诉它不是线程安全的。 它肯定有'lock'成员,它的方法在该锁对象下完全同步。

有人说PrintWriter.print方法不是线程安全的,但它是错误的。 PrintWriter.print调用write(),这绝对是线程安全的。 我们都知道write方法在'lock'下是同步的。 因此print方法是隐式/自然线程安全的。

PrintWriter.println应该自己同步,因为它调用print()和println(), 两者都是“独立的”线程安全的。

答案 3 :(得分:1)

取自here,其中一行代表:

多次写入底层输出流的PrintWriter的所有方法都在内部处理同步,因此PrintWriter对象是线程安全的。

答案 4 :(得分:1)

{ 
public void print(Object obj) 
     {

        write(String.valueOf(obj));
     }

     /* Methods that do terminate lines */

}

打印未同步...

因此,如果您使用的是print方法,请写下您自己的“我的作家”并同步它。

或者其他

如果你使用println()....然后它同步..

{

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

}

答案 5 :(得分:0)

不,它不是真正的线程安全。

请参阅PrintWriter.java here

中的write()方法

它们的写入是在锁定时定义的(已定义here - 这是Writer对象。如果它在此同步,它将是线程安全的,但在这种情况下它不是。