BTW, you can model a thread-safe random number generator without using a lock, replacing it with a CAS operation on a reference.
You still have problems this way, but at least it is non-blocking, in the sense that if the scheduler blocks any thread for any reason, then the other active threads can still have progress. And at least in Java, for a number of threads less or equal to the number of cores available, it will have better throughput, as locks these days are optimized for the common scenario of adding "just in case" synchronization (i.e. biased towards the thread that last acquired that lock), which hurts performance because of the extra management required.
You still have problems this way, but at least it is non-blocking, in the sense that if the scheduler blocks any thread for any reason, then the other active threads can still have progress. And at least in Java, for a number of threads less or equal to the number of cores available, it will have better throughput, as locks these days are optimized for the common scenario of adding "just in case" synchronization (i.e. biased towards the thread that last acquired that lock), which hurts performance because of the extra management required.