同步和System.out.println
如果多个线程没有同步调用System.out.println(String),输出可以交错? 该API没有提到同步,所以这似乎是可能的,或者是缓冲和/或虚拟机内存模型等阻止交错输出?
编辑:
例如,如果每个线程包含:
System.out.println("ABC");
是输出保证是:
ABC ABC
或者可能是:
AABC BC
由于API文档没有提到System.out
对象的线程安全性,也没有提到PrintStream#println(String)
方法 ,所以您不能假设它是线程安全的 。
但是,特定JVM的底层实现完全有可能使用println
方法的线程安全函数(例如glibc上的printf
),因此,实际上,根据第一个示例将保证输出(总是ABC\n
那么ABC\n
,从不穿插字符你的第二个例子)。 但请记住,有很多JVM实现,只需遵守JVM规范,而不是规范之外的任何约定。
如果您确实必须确保没有println调用会像您所描述的那样穿插,那么您必须手动强制执行互斥,例如:
public void safePrintln(String s) { synchronized (System.out) { System.out.println(s); } }
当然,这个例子只是一个例子,不应该被看作是“解决scheme”。 还有很多其他的因素需要考虑。
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
只要不通过System.setOut
更改OutputStream
,它就是线程安全的。
虽然它是线程安全的,但是可以有很multithreading写入System.out
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");
可以阅读
1 2 A 3 B C
以及其他组合。
所以要回答你的问题:
当你写入System.out
– 它获得了OutputStream
实例的一个锁 – 它将写入缓冲区并立即刷新。
一旦释放锁, OutputStream
被刷新并写入。 将不会有一个例子,你会有不同的stringjoin像1A 2B
。
编辑以回答您的编辑:
这不会发生在System.out.println
。 由于PrintStream
同步整个函数,它将填充缓冲区,然后以primefaces方式刷新它。 任何新的线程进入现在将有一个新的缓冲区工作。
为了澄清,说你有两个线程,一个打印"ABC"
,另一个打印"DEF"
。 你永远不会得到这样的输出: ADBECF
,但你也可以得到
ABC DEF
要么
DEF ABC