Issue unique ticket numbers from two threads with Interlocked.

interlocked `Interlocked.Increment` performs a small shared update atomically, so each thread receives a distinct result.

Atomic Ticket

start
AtomicTicket.cs
Replay: real traced execution (multi-file project)
using System;
using System.Threading;

class Program
{
    static int nextTicket;
    static int firstTicket;
    static int secondTicket;

    static void FirstWorker()
    {
        firstTicket = Interlocked.Increment(ref nextTicket);
    }

    static void SecondWorker()
    {
        secondTicket = Interlocked.Increment(ref nextTicket);
    }

    static void Main()
    {
        int start = 100;
        nextTicket = start;

        Thread first = new Thread(FirstWorker);
        Thread second = new Thread(SecondWorker);

        first.Start();
        second.Start();

        first.Join();
        second.Join();

        int issued = nextTicket - start;
        Console.WriteLine($"start={start}");
        Console.WriteLine($"issued={issued}");
    }
}
using System;
using System.Threading;

class Program
{
    static int nextTicket;
    static int firstTicket;
    static int secondTicket;

    static void FirstWorker()
    {
        firstTicket = Interlocked.Increment(ref nextTicket);
    }

    static void SecondWorker()
    {
        secondTicket = Interlocked.Increment(ref nextTicket);
    }

    static void Main()
    {
        int start = 10;
        nextTicket = start;

        Thread first = new Thread(FirstWorker);
        Thread second = new Thread(SecondWorker);

        first.Start();
        second.Start();

        first.Join();
        second.Join();

        int issued = nextTicket - start;
        Console.WriteLine($"start={start}");
        Console.WriteLine($"issued={issued}");
    }
}
using System;
using System.Threading;

class Program
{
    static int nextTicket;
    static int firstTicket;
    static int secondTicket;

    static void FirstWorker()
    {
        firstTicket = Interlocked.Increment(ref nextTicket);
    }

    static void SecondWorker()
    {
        secondTicket = Interlocked.Increment(ref nextTicket);
    }

    static void Main()
    {
        int start = 500;
        nextTicket = start;

        Thread first = new Thread(FirstWorker);
        Thread second = new Thread(SecondWorker);

        first.Start();
        second.Start();

        first.Join();
        second.Join();

        int issued = nextTicket - start;
        Console.WriteLine($"start={start}");
        Console.WriteLine($"issued={issued}");
    }
}
  1. start ← 100, nextTicket ← 100, first ← System.Threading.Thread

    20static void Main()21{22    int start→ 100 = 100; //@start=10, 50023    nextTicket→ 100 = start100;2425    Thread first→ System.Threading.Thread = new Thread(FirstWorker);26    Thread second→ System.Threading.Thread = new Thread(SecondWorker);2728    firstSystem.Threading.Thread.Start();29    secondSystem.Threading.Thread.Start();
  2. nextTicket ← 101, firstTicket ← 101

    10static void FirstWorker()11{12    firstTicket→ 101 = Interlocked.Increment(ref nextTicket→ 101);13}
  3. second.Start();

    28first.Start();29secondSystem.Threading.Thread.Start();3031firstSystem.Threading.Thread.Join();32secondSystem.Threading.Thread.Join();
  4. nextTicket ← 102, secondTicket ← 102

    15static void SecondWorker()16{17    secondTicket→ 102 = Interlocked.Increment(ref nextTicket→ 102);18}
  5. issued ← 2

    31    first.Join();32    secondSystem.Threading.Thread.Join();3334    int issued→ 2 = nextTicket102 - start100;35    Console.WriteLine($"start={start100}");36    Console.WriteLine($"issued={issued2}");37}
    outputstart=100
    issued=2
  1. start ← 10, nextTicket ← 10, first ← System.Threading.Thread, second ← System.Threading.Thread

    20static void Main()21{22    int start→ 10 = 10;23    nextTicket→ 10 = start10;2425    Thread first→ System.Threading.Thread = new Thread(FirstWorker);26    Thread second→ System.Threading.Thread = new Thread(SecondWorker);2728    firstSystem.Threading.Thread.Start();29    secondSystem.Threading.Thread.Start();
  2. nextTicket ← 11, firstTicket ← 11

    10static void FirstWorker()11{12    firstTicket→ 11 = Interlocked.Increment(ref nextTicket→ 11);13}
  3. second.Start();

    28first.Start();29secondSystem.Threading.Thread.Start();3031firstSystem.Threading.Thread.Join();32secondSystem.Threading.Thread.Join();
  4. nextTicket ← 12, secondTicket ← 12

    15static void SecondWorker()16{17    secondTicket→ 12 = Interlocked.Increment(ref nextTicket→ 12);18}
  5. issued ← 2

    31    first.Join();32    secondSystem.Threading.Thread.Join();3334    int issued→ 2 = nextTicket12 - start10;35    Console.WriteLine($"start={start10}");36    Console.WriteLine($"issued={issued2}");37}
    outputstart=10
    issued=2
  1. start ← 500, nextTicket ← 500, first ← System.Threading.Thread

    20static void Main()21{22    int start→ 500 = 500;23    nextTicket→ 500 = start500;2425    Thread first→ System.Threading.Thread = new Thread(FirstWorker);26    Thread second→ System.Threading.Thread = new Thread(SecondWorker);2728    firstSystem.Threading.Thread.Start();29    secondSystem.Threading.Thread.Start();
  2. nextTicket ← 501, firstTicket ← 501

    10static void FirstWorker()11{12    firstTicket→ 501 = Interlocked.Increment(ref nextTicket→ 501);13}
  3. second.Start();

    28first.Start();29secondSystem.Threading.Thread.Start();3031firstSystem.Threading.Thread.Join();32secondSystem.Threading.Thread.Join();
  4. nextTicket ← 502, secondTicket ← 502

    15static void SecondWorker()16{17    secondTicket→ 502 = Interlocked.Increment(ref nextTicket→ 502);18}
  5. issued ← 2

    31    first.Join();32    secondSystem.Threading.Thread.Join();3334    int issued→ 2 = nextTicket502 - start500;35    Console.WriteLine($"start={start500}");36    Console.WriteLine($"issued={issued2}");37}
    outputstart=500
    issued=2