I've not yet done a specific test on this but in other tests where I needed this behavior it seems to me that indeed threats blocked on a lock statement enter the lock in the same order with which they reached the lock section. Have I been only lucky or is this behavior indeed guaranteed?
UPDATE
Indeed using the following code I've been able to confirm that with the lock() statement ordered execution of threads is not guaranteed.
public static void Main()
{
Object objLock = new Object();
Stopwatch perf = new Stopwatch();
foreach (var batch in Enumerable.Range(1, 20))
{
perf.Restart();
var sequence = Enumerable.Range(1, 200);
var tickets = new List<int>();
var threads = sequence.Select(item =>
{
var thread = new Thread(() =>
{
lock (objLock)
{
tickets.Add(item);
Thread.Sleep(50);
}
});
Thread.Sleep(10);
thread.Start();
return thread;
}).ToArray();
foreach (var thread in threads) thread.Join();
Console.WriteLine($"Batch #{batch}, tickets: {String.Join(", ", tickets)} - " + (tickets.SequenceEqual(sequence) ? "OK" : "NOT FIFO!"));
Console.WriteLine($"Performance: { perf.ElapsedMilliseconds} ms");
}
Console.WriteLine(Environment.NewLine + "DONE");
Console.ReadLine();
}