PROWAREtech

articles » current » dot-net » random-is-not-thread-safe

.NET: The Random Class is Not Thread-safe!

How to use the Random class in a thread-safe manner to find reliable random values.

How not to use the Random class:


// This seems like it would work, but can generate duplicate sequences
Parallel.For(0, 10, i =>
{
	var localRandom = new Random(); // BAD! Could get same seed in different threads
	var number = localRandom.Next(1000);
	Console.WriteLine(number);
});

No, the C# Random class is not thread-safe. It maintains internal state that can be corrupted when accessed by multiple threads simultaneously. Here are three ways to make the Random class thread-safe:


// This demonstrates thread safety issues with Random
using System;
using System.Threading.Tasks;

class RandomThreadSafetyDemo
{
	// Shared Random instance - NOT thread-safe
	private static Random sharedRandom = new Random();

	// Thread-safe approach using ThreadLocal
	private static ThreadLocal<Random> threadLocalRandom = new ThreadLocal<Random>(() => new Random());

	// Another thread-safe approach using lock
	private static object lockObject = new object();

	public static void DemonstrateThreadSafetyIssues()
	{
		// This can produce duplicate numbers due to thread safety issues
		Parallel.For(0, 100, i =>
		{
			int number = sharedRandom.Next(1000);
			Console.WriteLine($"Unsafe number: {number}");
		});
	}

	public static void ThreadSafeApproach1()
	{
		// Using ThreadLocal - each thread gets its own Random instance
		Parallel.For(0, 100, i =>
		{
			int number = threadLocalRandom.Value.Next(1000);
			Console.WriteLine($"Thread-local number: {number}");
		});
	}

	public static void ThreadSafeApproach2()
	{
		// Using local copy of Random with unique seed
		Parallel.For(0, 100, i =>
		{
			var localRandom = new Random(Guid.NewGuid().GetHashCode()); // Unique seeds with local copy of Random
			var number = localRandom.Next(1000);
			Console.WriteLine($"Safe number: {number}");
		});
	}

	public static void ThreadSafeApproach3()
	{
		// Using lock - serializes access to shared Random
		Parallel.For(0, 100, i =>
		{
			int number;
			lock (lockObject) // May have concurrency issues and less performance, but yes, thread-safe
			{
				number = sharedRandom.Next(1000);
			}
			Console.WriteLine($"Locked number: {number}");
		});
	}
}

PROWAREtech

Hello there! How can I help you today?
Ask any question

PROWAREtech

This site uses cookies. Cookies are simple text files stored on the user's computer. They are used for adding features and security to this site. Read the privacy policy.
ACCEPT REJECT