using System.Collections.Generic;
public static void Main()
QueuedLock queuedLock = new QueuedLock();
foreach (var batch in Enumerable.Range(1, 10))
var sequence = Enumerable.Range(1, 10);
var tickets = new List<int>();
var threads = sequence.Select(_ =>
var thread = new Thread(() =>
var ticket = Interlocked.Increment(ref index);
queuedLock.Enter(); try { tickets.Add(ticket); Thread.Sleep(40); }
finally { queuedLock.Exit(); }
foreach (var thread in threads) thread.Join();
Console.WriteLine($"Batch #{batch}, tickets: {String.Join(", ", tickets)} - "
+ (tickets.SequenceEqual(sequence) ? "OK" : "NOT FIFO!"));
private readonly object _locker = new object();
private int _ticketsCount = 0;
private int _ticketToRide = 1;
if (Monitor.IsEntered(_locker)) throw new InvalidOperationException();
int myTicket = Interlocked.Increment(ref _ticketsCount);
while (myTicket != Volatile.Read(ref _ticketToRide))
if (!Monitor.IsEntered(_locker)) throw new InvalidOperationException();
Interlocked.Increment(ref _ticketToRide);
Monitor.PulseAll(_locker);