0

I have a code that manages a large queue of data, it's locked witch lock statement to ensure only a single thread is working on it at a time.

The order of data in queue is really important, and each thread with its parameters can either add or take from it.

How do I ensure threads are queued to start in order of FIFO like my queue? Does the lock statement guarantee this?

 var t = new Thread(() => parse(params));      //This is how I start my threads.
 t.Start();
user3200174
  • 81
  • 1
  • 5

2 Answers2

3

No, the lock statement does not guarantee FIFO ordering. Per Albahari:

If more than one thread contends the lock, they are queued on a “ready queue” and granted the lock on a first-come, first-served basis (a caveat is that nuances in the behavior of Windows and the CLR mean that the fairness of the queue can sometimes be violated).

If you want to ensure that your items are retrieved in a FIFO order, you should use the ConcurrentQueue<T> collection instead.

Edit: If you're targeting .NET 2.0, you could use a custom implementation for a concurrent thread-safe queue. Here's a trivial one:

public class ThreadSafeQueue<T>
{
    private readonly object syncLock = new object();
    private readonly Queue<T> innerQueue = new Queue<T>();

    public void Enqueue(T item)
    {
        lock (syncLock)
            innerQueue.Enqueue(item);
    }

    public bool TryDequeue(out T item)
    {
        lock (syncLock)
        {
            if (innerQueue.Count == 0)
            {
                item = default(T);
                return false;
            }

            item = innerQueue.Dequeue();
            return true;
        }
    }
}
Douglas
  • 53,759
  • 13
  • 140
  • 188
  • Thanks a lot but I am writing a TCP socket library and compatibility is a bit of an issue. Is there's anything similar for .Net framework 2.0? – user3200174 Jan 17 '14 at 17:13
  • I'm not sure I understood your original issue. Only one thread will be reading from the socket at any time, correct? Does it matter which thread that is? – Douglas Jan 17 '14 at 17:17
  • In the MSDN page, ConcurrentQueue is only available for .Net 4.0 and upwards. I'm looking for something that can be compiled with .Net 2.0 for maximum compatibility. – user3200174 Jan 17 '14 at 17:26
  • 2
    https://bitbucket.org/JonHanna/ariadne has a concurrent queue that while written for 4.0 can be converted to 2.0 by just removing it's support for `IProducerConsumerCollection`. To add to Douglas' answer, `lock` depends on underlying OS features which in Windows since 2003 leans toward FIFO but deliberately avoid it for better concurrency (e.g. don't wake a suspended thread when a new arrival is still live) and to avoid lock convoys. – Jon Hanna Jan 17 '14 at 17:37
  • The queue in the edit isn't a concurrent queue, it's a queue that offers thread safety by making sure it *isn't* concurrent. It'll give better performance if concurrent access is rare but has to be safe when it does happen, but if concurrent access is common, you'd want a real concurrent queue. – Jon Hanna Jan 17 '14 at 17:43
  • @JonHanna: You're correct; I've fixed my edit. I don't know enough about the OP's issue to tell whether lock contention will be an issue. – Douglas Jan 17 '14 at 17:53
  • If it is, http://stackoverflow.com/a/3871198/400547 has a simpler version of that in Ariadne, though one does really only need to comment out `using System.Collections.Concurrent;` and `IProducerConsumerCollection,` in the Ariadne's to have it compile with 2.0. I should really do a multi-targeted version of that library. – Jon Hanna Jan 17 '14 at 18:00
1

Lock does't guarantee First In First Out access. An alternate approach would be Queue if you are limited with .NET 2.0. Keep in mind that, Queue is not thread safe hence you should synchronize the access.

S.N
  • 4,910
  • 5
  • 31
  • 51