Reputation: 23
I stumbled upon the source code of System.console() and I'm unsure why exactly it is implemented like this:
/**
* Returns the unique {@link java.io.Console Console} object associated
* with the current Java virtual machine, if any.
*
* @return The system console, if any, otherwise {@code null}.
*
* @since 1.6
*/
public static Console console() {
Console c;
if ((c = cons) == null) {
synchronized (System.class) {
if ((c = cons) == null) {
cons = c = SharedSecrets.getJavaIOAccess().console();
}
}
}
return c;
}
More specifically, what is the point of the assignments to c
? The variable cons
is already static and holds the console object.
Upvotes: 2
Views: 92
Reputation: 545875
tl;dr: It’s a common optimisation technique.
This pattern is called double-checked locking.
The implementation could also just look much simpler, as follows:
public static synchronized Console console() {
if (cons == null) {
cons = SharedSecrets.getJavaIOAccess().console();
}
return cons;
}
However, that way we would always lock the entire System
class for every single call of the console
method, which would lead to a substantial slowdown in typical applications.
Instead, the actual implementation defensively locks the object only if it can’t acquire a valid cons
instance. And it assigns the result to a local variable c
so that this instance remains valid even if another thread overrides cons
after the (unlocked) check happens. It also helps reduce reading the cons
reference, which is declared as volatile
, and reading it is thus slower than reading a non-volatile reference.
Upvotes: 4