Is multi-thread output from System.out.println interleaved
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.
Is System.out.println thread-safe by default?
Since the documentation of PrintStream
, its superclass FilterStream
, and its superclass OutputStream
all fail to say anything about thread safety or synchronization, in theory you cannot rely on it, it's not part of the contract.
I think it would be surprising if someone produced a PrintStream
class that didn't do what Oracle's does in this regard, but I've been surprised before.
Is Java's System.out.println() method mutually exclusive to threads by default?
Since the implementation of println
is synchronized on that instance, there's virtually no chance that the stream will self-corrupt.
If you have different threads printing different things, however, you may see non-deterministic behavior in that the order you perceive things to be printed isn't the order in which they actually are. That's a separate concern to the actual corruption of the stream you're writing to.
Stop threads from interleaving output
The way to handle output with STM is to have an output queue that is shared between all threads and which is processed by a single thread.
import Control.Concurrent
import Control.Concurrent.STM
import Control.Monad
import System.Random
randomDelay t = randomRIO (0, t) >>= threadDelay
printer queue str = forkIO . forever $ do
randomDelay 1000000 -- μs
atomically $ writeTChan queue str
prepareOutputQueue = do
queue <- newTChanIO
forkIO . forever $ atomically (readTChan queue) >>= putStrLn
return queue
main = do
queue <- prepareOutputQueue
printer queue "Hello"
printer queue "World"
return ()
Java MultiThreading output seemingly ambiguous on thread-safe System.out
This is what happens in you example:
Main thread:
- create first thread: info = "a" (1)
- start Thread1 (2)
- sleep 1 millisecond (3)
- create second thread: info = "ab" (4)
- start Thread2 (5)
Thread1:
- prints first line: "a" (7) -> even though info was already changed to "ab" by Main thread, it is not yet visible to Thread1
- prints second line: "ab" (8)
Thread2:
- prints first line: "ab" (6)
- prints second line: "ab" (9)
Observations
- Calling
sleep
does not offer any contract that Thread1 will start execution before Thread2. It is up to the thread scheduler of the OperatingSystem to decide which thread will start execution first and there is no deterministic ordering between them in this case. - Thread1 can read a stale value from
info
, since there is no happens before relation on memory actions for this field.
Volatile
To avoid seeing a stale value of the info
field, one could declare it as volatile
. This will ensure that a write to this field 'happens before; any subsequent read.
More about happens before relations and memory visibility here: Memory Consistency Properties
Statement execution interleaving with Synchronized method execution
The synchronized
keyword prevents two threads from running code that is synchronized on the same object.
Each of your threads are synchronizing on a different object (this
), so it has no effect.
Related Topics
What's Java Hybrid - Applet + Application
Split String With Dot as Delimiter
Android: How to Get the Current Day of the Week (Monday, etc...) in the User's Language
How Set Background Drawable Programmatically in Android
How to Support Both Ipv4 & Ipv6 on Java
How to Start Using and Developing on Ubuntu Linux
The Encoding 'Utf-8' Is Not Supported by the Java Runtime
Execute Bash Command Within Java Program
How to Fix Java.Awt.Headlessexception in Jenkins on Linux
Multiple Row Selection in Jtable
Is Multi-Thread Output from System.Out.Println Interleaved
Android Custom Row Item for Listview
How to Encode a Wav to a Mp3 on a Android Device
Java System Preferences Under Different Users in Linux
Java I/O VS. Java New I/O (Nio) with Linux Nptl
Local_Policy.Jar and Us_Export_Policy.Jar Different with Unlimited Strength VS Default