Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a synchronization class that guarantee FIFO order in C#?

What is it and how to use?

I need that as I have a timer that inserts into DB every second, and I have a shared resource between timer handler and the main thread. I want to gurantee that if the timer handler takes more than one second in the insertion the waited threads should be executed in order. This is a sample code for my timer handler:

private void InsertBasicVaraibles(object param)
{
    try
    {
        DataTablesMutex.WaitOne();//mutex for my shared resources
         //insert into DB
    }
    catch (Exception ex)
    {
        //Handle
    }
    finally
    {
        DataTablesMutex.ReleaseMutex();
    }
}

But currently the mutex does not guarantee any order.

like image 739
Ahmed Avatar asked Jun 07 '09 13:06

Ahmed


3 Answers

You'll need to write your own class to do this, I found this example (pasted because it looks as though the site's domain has lapsed):

using System.Threading;

public sealed class QueuedLock
{
    private object innerLock;
    private volatile int ticketsCount = 0;
    private volatile int ticketToRide = 1;

    public QueuedLock()
    {
        innerLock = new Object();
    }

    public void Enter()
    {
        int myTicket = Interlocked.Increment(ref ticketsCount);
        Monitor.Enter(innerLock);
        while (true)
        {

            if (myTicket == ticketToRide)
            {
                return;
            }
            else
            {
                Monitor.Wait(innerLock);
            }
        }
    }

    public void Exit()
    {
        Interlocked.Increment(ref ticketToRide);
        Monitor.PulseAll(innerLock);
        Monitor.Exit(innerLock);
    }
}

Example of usage:

QueuedLock queuedLock = new QueuedLock();

try
{
   queuedLock.Enter();
   // here code which needs to be synchronized
   // in correct order
}
finally
{
    queuedLock.Exit();
}

Source via archive.org

like image 148
Matt Brindley Avatar answered Oct 18 '22 13:10

Matt Brindley


Just reading Joe Duffy's "Concurrent Programming on Windows" it sounds like you'll usually get FIFO behaviour from .NET monitors, but there are some situations where that won't occur.

Page 273 of the book says: "Because monitors use kernel objects internally, they exhibit the same roughly-FIFO behavior that the OS synchronization mechanisms also exhibit (described in the previous chapter). Monitors are unfair, so if another thread sneaks in and acquires the lock before an awakened waiting thread tries to acquire the lock, the sneaky thread is permitted to acquire the lock."

I can't immediately find the section referenced "in the previous chapter" but it does note that locks have been made deliberately unfair in recent editions of Windows to improve scalability and reduce lock convoys.

Do you definitely need your lock to be FIFO? Maybe there's a different way to approach the problem. I don't know of any locks in .NET which are guaranteed to be FIFO.

like image 39
Jon Skeet Avatar answered Oct 18 '22 13:10

Jon Skeet


You should re-design your system to not rely on the execution order of the threads. For example, rather than have your threads make a DB call that might take more than one second, have your threads place the command they would execute into a data structure like a queue (or a heap if there is something that says "this one should be before another one"). Then, in spare time, drain the queue and do your db inserts one at a time in the proper order.

like image 41
JP Alioto Avatar answered Oct 18 '22 13:10

JP Alioto