Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lock that will allow multiple readers in C#

I have the following code:

private static object _dbLock = new object();

public static void LoadData()
{
   lock (_dbLock)
   {
      //Load data from the database
   }
}

public static string ReadData(Guid key)
{
   lock (_dbLock)
   {
      //Lookup key in data and return value
   }
}

I don't want to allow people to read the data while it's being loaded from the database, thus I put a lock in ReadData. However, right now if multiple people call ReadData at the same time, only one call can run at once.

Is there a way I can allow simultaneous calls to ReadData but block readers when LoadData is being run?

like image 870
Mike Christensen Avatar asked Oct 17 '12 01:10

Mike Christensen


People also ask

What is read/write lock in C?

In many situations, data is read more often than it is modified or written. In these cases, you can allow threads to read concurrently while holding the lock and allow only one thread to hold the lock when data is modified. A multiple-reader single-writer lock (or read/write lock) does this.

Which lock allows both read and write operations?

An RW lock allows concurrent access for read-only operations, write operations require exclusive access. This means that multiple threads can read the data in parallel but an exclusive lock is needed for writing or modifying data.

What is a reading lock?

A readers/writer lock regulates access to a set of data. The readers/writer lock is so called because many threads can hold the lock simultaneously for reading, but only one thread can hold the lock for writing. Most device drivers do not use readers/writer locks.

How is Rwlock implemented?

Instead of having a single lock method, they have two - one for readers and one for writers. When readers enter the critical section they invoke the reader lock (and then reader unlock on exit); when writers enter the critical section they invoke the writer lock (and then writer unlock on exit).


2 Answers

The ReaderWriterLock and ReaderWriterLockSlim classes support that use case. Use the 'Slim' version unless you need pre-3.5 support.

private static ReaderWriterLockSlim _cacheLock = new ReaderWriterLockSlim();

public static void LoadData()
{
    _cacheLock.EnterWriteLock();
    try
    {
        // Load data from the database
    }
    finally
    {
        _cacheLock.ExitWriteLock();
    }
}

public static string ReadData(Guid key)
{
    _cacheLock.EnterReadLock();
    try
    {
        // Lookup key in data and return value
    }
    finally
    {
        _cacheLock.ExitReadLock();
    }
}
like image 94
JohnnyHK Avatar answered Oct 13 '22 01:10

JohnnyHK


Try using the ManualResetEvent:

private static object _dbLock = new object();
private static ManualResetEvent _mrse = new ManualResetEvent(true);

public static void LoadData()
{

   lock (_dbLock)
   {
      _mrse.Reset();
      //Load data from the database
      _mrse.Set();
   }
}

public static string ReadData(Guid key)
{
    _mrse.Wait();
    //Lookup key in data and return value
}

This allows multiple readers to wait for the data loader to finish its work and then simultaneously read. If the collection is not thread safe, then you need to add another locking object or use another synchronization construct.

like image 21
Kiril Avatar answered Oct 13 '22 01:10

Kiril