是来自 System.out.println 的多线程输出交错的

如果多个线程在没有同步的情况下调用 System.out.println(String),输出是否可以交错?还是每行的写入是原子的?API没有提到同步,所以这似乎是可能的,或者通过缓冲和/或VM内存模型等阻止了交错输出?

编辑:

例如,如果每个线程包含:

System.out.println("ABC");

是保证为以下各项的输出:

ABC
ABC

或者可能是:

AABC
BC

答案 1

由于 API 文档没有提到 System.out 对象上的线程安全,也没有提到 PrintStream#println(String) 方法,因此您不能假定它是线程安全的

但是,完全有可能特定JVM的基础实现使用线程安全函数作为该方法(例如glibc上的printf),因此,实际上,输出将保证每个第一个示例(始终如此,永远不要在每个第二个示例中穿插字符)。但请记住,有很多JVM实现,它们只需要遵守JVM规范,而不是该规范之外的任何约定。printlnABC\nABC\n

如果您绝对必须确保没有 println 调用会像您描述的那样穿插,那么您必须手动强制执行互斥,例如:

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

当然,这个例子只是一个例证,不应被视为“解决办法”;还有许多其他因素需要考虑。例如,仅当所有代码都使用该方法并且没有直接调用时,上述方法才是安全的。safePrintln(...)System.out.println(...)


答案 2

OpenJDK源代码回答了你的问题:

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

参考资料: http://hg.openjdk.java.net/jdk6/jdk6/jdk/file/39e8fe7a0af1/src/share/classes/java/io/PrintStream.java