Generating random numbers is a common task, but System.Random
in older .NET versions (including .NET Framework up to 4.8.x and .NET Core prior to 6.0) presents a well-known challenge: it's not thread-safe. Accessing a single Random
instance from multiple threads concurrently can lead to corrupted internal state and output sequences that are far from random (often returning zeroes).
A popular solution often found online involves wrapping System.Random
within a ThreadLocal<T>
or using the [ThreadStatic]
attribute. Articles like Andrew Lock's post and implementations such as ThreadSafeRandomizer showcase variations of this pattern. The core idea is to create a shared Random
instance used only to seed thread-specific Random
instances lazily.