CodeBlanks Logo Icon CodeBlanks

Summary - Thread and ThreadPool

C# course · Expert · Lesson 24/47

Combine Thread, lock and Interlocked to write a counter.

Summary - Thread and ThreadPool

In this group you learned the Thread class, Start/Join synchronization, ThreadPool, the lock statement and Interlocked.

These are the foundations of low-level parallel programming. Modern C# prefers Task/async in most cases, but Thread, lock and Interlocked are still important tools. Let's now write two counter examples.

Exercise Increment 5 times each with lock

Declare private static readonly object _sync = new object(); and private static int _counter = 0;. In Main create 2 threads, each calling for (int i = 0; i < 5; i++) { lock (_sync) { _counter++; } }. Wait with Join. Print Console.WriteLine($"Counter: {_counter}");. (2 threads * 5 increments = 10 expected.)

Show example solution
Thread t1 = new Thread(() => { for (int i = 0; i < 5; i++) { lock (_sync) { _counter++; } } }); Thread t2 = new Thread(() => { for (int i = 0; i < 5; i++) { lock (_sync) { _counter++; } } }); t1.Start(); t2.Start(); t1.Join(); t2.Join(); Console.WriteLine($"Counter: {_counter}");
Example solution:
using System;
using System.Threading;

class Program
{
    private static readonly object _sync = new object();
    private static int _counter = 0;

    static void Main()
    {
        Thread t1 = new Thread(() => {
            for (int i = 0; i < 5; i++) { lock (_sync) { _counter++; } }
        });
        Thread t2 = new Thread(() => {
            for (int i = 0; i < 5; i++) { lock (_sync) { _counter++; } }
        });
        t1.Start();
        t2.Start();
        t1.Join();
        t2.Join();
        Console.WriteLine($"Counter: {_counter}");
    }
}

ThreadPool and Interlocked together

When you keep a shared counter across work items on the ThreadPool, Interlocked is the cleanest solution. It is much faster than a lock; each item runs on its own thread but Interlocked guarantees atomicity.

This pattern fits, for example, keeping a request counter in a web server. The code is both safe and high-performance.

Exercise Increment 3 times each with Interlocked

Declare private static int _counter = 0;. In Main create 2 threads, each calling for (int i = 0; i < 3; i++) { Interlocked.Increment(ref _counter); }. Wait with Join. Print Console.WriteLine($"Counter: {_counter}");. (2 threads * 3 increments = 6 expected.)

Show example solution
Thread t1 = new Thread(() => { for (int i = 0; i < 3; i++) { Interlocked.Increment(ref _counter); } }); Thread t2 = new Thread(() => { for (int i = 0; i < 3; i++) { Interlocked.Increment(ref _counter); } }); t1.Start(); t2.Start(); t1.Join(); t2.Join(); Console.WriteLine($"Counter: {_counter}");
Example solution:
using System;
using System.Threading;

class Program
{
    private static int _counter = 0;

    static void Main()
    {
        Thread t1 = new Thread(() => {
            for (int i = 0; i < 3; i++) { Interlocked.Increment(ref _counter); }
        });
        Thread t2 = new Thread(() => {
            for (int i = 0; i < 3; i++) { Interlocked.Increment(ref _counter); }
        });
        t1.Start();
        t2.Start();
        t1.Join();
        t2.Join();
        Console.WriteLine($"Counter: {_counter}");
    }
}

Test yourself

  1. Which provides atomic increment without a lock?

    • counter++
    • Interlocked.Increment
    • lock (counter)
    • Thread.Sleep
    Show answer

    Interlocked.Increment — Correct. Interlocked.Increment atomically increments without a lock.

  2. Match the concepts

    Thread
    Separate thread
    ThreadPool
    Ready pool
    lock
    Critical section
    Interlocked
    Atomic operation

All lessons in Expert