Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
proposal: math/rand: Expose constructor for `lockedSource` #24121
The proposal is to expose a constructor for the
Today, users who need a thread-safe implementation must duplicate the
Why do users need a thread-safe source? One reason is that such a source is necessary when implementing any object that (1) exposes thread-safe methods which use random numbers in their implementation and (2) supports dependency injection.
Incidentally, the proposed rand package for Go 2 (#21835) goes even further than this proposal and makes LockedSource a public type.
I think that we should consider all Go 2 math/rand proposals together to get a coherent picture. The home for that should probably be #21835. I think we should backlink here from #21835 and close this.
If we do something like this, I think a better API would be:
func NewLockedSource(src Source) Source
Then it could be usefully used with any input source.
It's not a matter of whether it's difficult or not, but what the defaults encourage. At present,
And because there's neither a constructor function in the standard library for a locked source nor an interface definition, there isn't really a way for different libraries to standardize around a common interface for requiring a threadsafe source even if they want to. Either one by itself would suffice, but without either one, people reach for the most convenient default, which has led to the problems we're currently observing:
a) a lot of packages duplicate the lockedSource implementation verbatim, which is a sign that people would find it valuable if it were exported
b) too many packages rely on the default Source
where I'm using "too many" in this context to mean "enough to provide noticeable mutex contention for applications which use these packages, even under modest workloads".
As I wrote over in #21393, there may be some subtleties and/or optimizations that just throwing a mutex at won't help with, like batching core PRNG calls for rand.Read. But yes, it doesn't seem like a high priority.
* By using a sync.Pool, we can preserve the current behavior for the single-threaded, serialized case (seeded with 1), but also allow concurrent callers the ability to generate random numbers with the default source without blocking on the same global mutex golang#24121 (comment) Change-Id: Icf10fdf10f96775ea64bc52202c41bf023d299de