Parallel.For, Thread Safety, Locks & Concurrent Collections Masterclass

โšก C# 12 & .NET 8 ๐ŸŸข Chapter 29 of 35 ๐Ÿ“‚ Phase 10: Asynchronous Programming ๐Ÿ“… 2026 Edition
๐Ÿ“Œ Covered in this chapter: Parallelism vs Async ยท Parallel.For ยท Parallel.ForEach ยท Thread Safety ยท Race Conditions ยท lock ยท Interlocked ยท ConcurrentDictionary

Welcome to Phase 10 (Chapter 29): C# Parallel Programming, Parallel.For, Thread Safety & Concurrent Collections Masterclass! Parallel programming exploits multi-core CPU processors by distributing independent work across multiple threads simultaneously. In this chapter, we master Parallel.For, Parallel.ForEach, Task Parallel Library (TPL), thread safety, race conditions, lock, Monitor, Interlocked, concurrent collections (ConcurrentBag, ConcurrentDictionary), and performance considerations.

1Parallelism Ante Enti? Async vs Parallel
Conceptasync/awaitParallel Programming
Core PurposeHandles I/O-Bound waits (network, disk) without blocking threadMaximizes CPU usage for CPU-Bound computation across cores
Thread UsageSingle logical thread, released during I/O waitMultiple physical threads running simultaneously
Best ForHTTP requests, file reads, database queriesData processing, image rendering, number crunching
2Parallel.For & Parallel.ForEach
C# โ€” Parallel.For & Parallel.ForEach โ–ถ Run in Compiler
using System.Threading.Tasks;

// 1. Parallel.For โ€” Distributes loop iterations across CPU cores
Parallel.For(0, 5, i =>
{
    Console.WriteLine($"Parallel task {i} on Thread {Thread.CurrentThread.ManagedThreadId}");
});

// 2. Parallel.ForEach โ€” Parallel iteration over a collection
string[] cities = { "Hyderabad", "Bangalore", "Mumbai", "Delhi", "Chennai" };

Parallel.ForEach(cities, city =>
{
    Console.WriteLine($"Processing city: {city} (Thread {Thread.CurrentThread.ManagedThreadId})");
});
3Thread Safety & Locks โ€” Race Conditions
C# โ€” Thread Safety with lock โ–ถ Run in Compiler
int counter = 0;
object lockObject = new object();

Parallel.For(0, 1000, _ =>
{
    // lock ensures only ONE thread enters this block at a time
    lock (lockObject)
    {
        counter++;
    }
});

Console.WriteLine($"Final Counter: {counter}"); // Always 1000 (thread-safe!)

// Alternative: Interlocked.Increment (lock-free atomic increment)
int atomicCounter = 0;
Parallel.For(0, 1000, _ => Interlocked.Increment(ref atomicCounter));
Console.WriteLine($"Interlocked Counter: {atomicCounter}");
4Technical FAQs

Q1: What is a Race Condition?

A race condition occurs when two or more threads access and modify a shared variable simultaneously without synchronization, producing unpredictable and incorrect results (e.g., counter never reaching 1000 without lock).

Q2: When should I use ConcurrentDictionary vs Dictionary?

Use ConcurrentDictionary<K,V> from System.Collections.Concurrent when multiple threads need to read and write dictionary entries simultaneously. Standard Dictionary is NOT thread-safe.