mardi 15 novembre 2016

Why is ThreadLocalRandom implemented so bizarrely?

This question regards the implementation of ThreadLocalRandom in OpenJDK version 1.8.0.

ThreadLocalRandom provides a per-thread random number generator without the synchronization overhead imposed by Random. The most obvious implementation (IMO) would be something like this, which appears to preserve backward compatibility without much complexity:

public class ThreadLocalRandom extends Random {
    private static final ThreadLocal<ThreadLocalRandom> tl =
        ThreadLocal.withInitial(ThreadLocalRandom::new);
    public static ThreadLocalRandom current() {
        return tl.get();
    }
    // Random methods moved here without synchronization
    // stream methods here
}

public class Random {
    private ThreadLocalRandom delegate = new ThreadLocalRandom();
    // methods synchronize and delegate for backward compatibility
}

However, the actual implementation is totally different and quite bizarre:

  • ThreadLocalRandom duplicates some of the methods in Random verbatim and others with minor modifications; surely much of this code could have been reused.
  • Thread stores the seed and a probe variable used to initialize the `ThreadLocalRandom, violating encapsulation;
  • ThreadLocalRandom uses Unsafe to access the variables in Thread, which I suppose is because the two classes are in different packages yet the state variables must be private in Thread - Unsafe is only necessary because of the encapsulation violation;
  • ThreadLocalRandom stores its next nextGaussian in a static ThreadLocal instead of in an instance variable as Random does.

Overall my cursory inspection seems to reveal an ugly copy of Random with no advantages over the simple implementation above. But the authors of the standard library are smart so there must be some reason for this weird approach. Does anyone have any insight into why ThreadLocalRandom was implemented this way?




Aucun commentaire:

Enregistrer un commentaire