The original source code looks like
public static void shuffle(List<?> list) {
Random rnd = r;
if (rnd == null)
r = rnd = new Random(); // harmless race.
shuffle(list, rnd);
}
and hints to the point behind the design. The code uses the shared field r
and is not thread safe, but designed in a way that the consequences are “harmless”.
Obviously, you should not design your software in that way. That’s left to the experts for certain software where they think, performance matters. (Actually, that shuffle
method might not belong to this category)
So for your alternative
private static Random r;
public static void shuffle(List<?> var0) {
if (r == null) {
r = new Random();
}
shuffle(var0, r);
}
the consequences of the missing thread safety would not be harmless. The test r == null
and the subsequent invocation shuffle(var0, r)
bear distinct reads of r
and while there should only be transitions from the initial null
to an initialized Random
instance, reads and writes can be perceived out of order when no thread safe mechanism is used, so when a concurrent write happens, r == null
could evaluate to false
while the subsequent shuffle(var0, r)
reads null
.
This doesn’t make this variant wrong. If you document your method or the containing class as not being thread safe and requiring external synchronization when being used by different threads, there would be nothing wrong.
The shuffle
method of the Collections
class reads the value of r
into a local variable, to ensure that the same value will be used by the rnd == null
test and the shuffle(list, rnd)
call. Since this may read a reference to a Random
instance created by another thread, it relies on the fact that the Random
instance is thread safe on its own, as otherwise, a racy read could exhibit an inconsistent object state.
It is still possible that the read misses a value previously written by another thread or that a write by another thread happens between the read of null
and the subsequent write of a reference to a newly create Random
instance. So it is possible that multiple threads will construct and use different Random
instances here, which is considered within the “harmless” consequences.
As said, you should not copy this pattern. Rather, decide for either, thread safety or no thread safety, and document your code as such.