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(item =>
var thread = new Thread(() =>
try { tickets.Add(item); 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 != _ticketToRide) Monitor.Wait(_locker);
if (!Monitor.IsEntered(_locker)) throw new InvalidOperationException();
Monitor.PulseAll(_locker);