Proper Usage of Random Number Generator in C# and Thread-Safety Practices

Nov 25, 2025 · Programming · 11 views · 7.8

Keywords: C# | Random Number Generation | Random Class | Thread Safety | Singleton Pattern | Pseudo-random Numbers

Abstract: This article provides an in-depth analysis of the Random class usage issues in C#, explaining why repeated instantiation in loops generates identical random numbers. Through practical code examples, it demonstrates how to ensure true randomness using singleton patterns and thread synchronization mechanisms, while discussing thread safety in multi-threaded environments and solutions including lock synchronization and ThreadLocal instantiation approaches.

Problem Phenomenon and Root Cause Analysis

In C# programming, many developers encounter issues where random number generators produce duplicate values. Specifically, when calling random number generation functions multiple times within loops, the generated values are identical, contradicting the expected randomness.

The root cause lies in the instantiation mechanism of the Random class. The default constructor of the Random class uses the system clock as the seed value. When multiple Random instances are created consecutively in tight loops, due to the computer's high execution speed, these instances may use the same timestamp as the seed, resulting in identical random number sequences.

Solution: Application of Singleton Pattern

The correct approach is to create a single Random instance and reuse it throughout the application. This ensures the continuity of the random number sequence and avoids seed repetition issues.

// Create static Random instance
private static readonly Random random = new Random();

// Random number generation function
public static int RandomNumber(int min, int max)
{
    return random.Next(min, max);
}

Thread Safety in Multi-threaded Environments

In multi-threaded applications, multiple threads accessing the same Random instance simultaneously may corrupt its internal state. The Next method of the Random class modifies the instance's internal state, and if multiple threads call this method concurrently, it may disrupt the correctness of the random number generation algorithm.

Solution One: Synchronization using Lock Mechanism

private static readonly Random random = new Random();
private static readonly object syncLock = new object();

public static int RandomNumber(int min, int max)
{
    lock(syncLock)
    {
        return random.Next(min, max);
    }
}

Solution Two: Thread Isolation using ThreadLocal

private static readonly ThreadLocal<Random> appRandom 
    = new ThreadLocal<Random>(() => new Random());

public static int RandomNumber(int min, int max)
{
    return appRandom.Value.Next(min, max);
}

Types and Principles of Random Number Generators

Random number generators are mainly divided into Pseudo-Random Number Generators (PRNG) and True Random Number Generators (TRNG). The Random class in C# belongs to pseudo-random number generators, which produce seemingly random number sequences through deterministic algorithms. Although these numbers are statistically random, due to the deterministic nature of the algorithm, identical seeds will produce identical sequences.

True random number generators rely on the randomness of physical processes, such as atmospheric noise or radioactive decay, to generate truly random sequences. In applications requiring high security, cryptographically secure random number generators should be considered.

Practical Application Scenarios

Random number generation has wide applications in programming:

Best Practice Recommendations

1. Avoid Repeated Instantiation: Use a single Random instance throughout the application lifecycle

2. Consider Thread Safety: Appropriate synchronization measures must be taken in multi-threaded environments

3. Seed Management: Use fixed seeds for reproducible testing scenarios; let the system automatically select seeds for true randomness requirements

4. Range Control: When using the Next(min, max) method, note that the maximum value is exclusive, with the actual range being [min, max-1]

By following these best practices, you can ensure the generation of high-quality, truly random number sequences in C# applications, meeting the requirements of various business scenarios.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.