Use ReaderWriter Lock in C#

The ReaderWriterLock class in C# provides synchronized access to a resource by allowing multiple threads to read simultaneously while ensuring exclusive access for writing operations. It offers better performance than Monitor for scenarios where reads are frequent and writes are infrequent.

Note: ReaderWriterLock is obsolete since .NET 3.5. The recommended alternative is ReaderWriterLockSlim, which provides better performance and functionality.

Syntax

Following is the syntax for declaring a ReaderWriterLock −

static ReaderWriterLock rwLock = new ReaderWriterLock();

Following is the syntax for acquiring and releasing locks −

// Acquire reader lock
rwLock.AcquireReaderLock(timeout);
try {
    // Read operations
}
finally {
    rwLock.ReleaseReaderLock();
}

// Acquire writer lock
rwLock.AcquireWriterLock(timeout);
try {
    // Write operations
}
finally {
    rwLock.ReleaseWriterLock();
}

How ReaderWriterLock Works

ReaderWriterLock Behavior Multiple Readers Thread 1: Reading Thread 2: Reading Single Writer Thread 3: Writing (Exclusive access) ? Concurrent reads allowed ? Blocks all other operations Readers can access simultaneously Writer requires exclusive access

Properties

Property Description
IsReaderLockHeld Gets a value indicating whether the current thread holds a reader lock.
IsWriterLockHeld Gets a value indicating whether the current thread holds a writer lock.
WriterSeqNum Gets the current sequence number that can be used to determine whether a writer lock was taken since the sequence number was obtained.

Key Methods

Method Description
AcquireReaderLock(TimeSpan) Acquires a reader lock, using a TimeSpan value for the timeout.
AcquireWriterLock(TimeSpan) Acquires a writer lock, using a TimeSpan value for the timeout.
ReleaseReaderLock() Decrements the lock count and releases a reader lock.
ReleaseWriterLock() Decrements the lock count and releases a writer lock.

Using ReaderWriterLock for Shared Data

Example

using System;
using System.Threading;

class SharedResource {
    private static ReaderWriterLock rwLock = new ReaderWriterLock();
    private static int sharedData = 0;

    public static void ReadData(string threadName) {
        rwLock.AcquireReaderLock(5000);
        try {
            Console.WriteLine($"{threadName} reading: {sharedData}");
            Thread.Sleep(1000); // Simulate read operation
        }
        finally {
            rwLock.ReleaseReaderLock();
        }
    }

    public static void WriteData(string threadName, int value) {
        rwLock.AcquireWriterLock(5000);
        try {
            Console.WriteLine($"{threadName} writing: {value}");
            sharedData = value;
            Thread.Sleep(1000); // Simulate write operation
        }
        finally {
            rwLock.ReleaseWriterLock();
        }
    }
}

class Program {
    public static void Main() {
        Thread reader1 = new Thread(() => SharedResource.ReadData("Reader1"));
        Thread reader2 = new Thread(() => SharedResource.ReadData("Reader2"));
        Thread writer1 = new Thread(() => SharedResource.WriteData("Writer1", 42));

        reader1.Start();
        reader2.Start();
        writer1.Start();

        reader1.Join();
        reader2.Join();
        writer1.Join();

        Console.WriteLine("All threads completed.");
    }
}

The output of the above code is −

Reader1 reading: 0
Reader2 reading: 0
Writer1 writing: 42
All threads completed.

ReaderWriterLockSlim Alternative

Since ReaderWriterLock is obsolete, here's the recommended ReaderWriterLockSlim approach −

Example

using System;
using System.Threading;

class ModernSharedResource {
    private static ReaderWriterLockSlim rwLockSlim = new ReaderWriterLockSlim();
    private static int sharedValue = 100;

    public static void ReadValue() {
        rwLockSlim.EnterReadLock();
        try {
            Console.WriteLine($"Current value: {sharedValue}");
        }
        finally {
            rwLockSlim.ExitReadLock();
        }
    }

    public static void WriteValue(int newValue) {
        rwLockSlim.EnterWriteLock();
        try {
            Console.WriteLine($"Updating value to: {newValue}");
            sharedValue = newValue;
        }
        finally {
            rwLockSlim.ExitWriteLock();
        }
    }
}

class Program {
    public static void Main() {
        ModernSharedResource.ReadValue();
        ModernSharedResource.WriteValue(200);
        ModernSharedResource.ReadValue();
        
        Console.WriteLine("ReaderWriterLockSlim example completed.");
    }
}

The output of the above code is −

Current value: 100
Updating value to: 200
Current value: 200
ReaderWriterLockSlim example completed.

Comparison

ReaderWriterLock ReaderWriterLockSlim
Obsolete since .NET 3.5 Recommended for new development
Higher memory overhead Lower memory footprint
Supports recursion by default Recursion must be explicitly enabled
AcquireReaderLock() / ReleaseReaderLock() EnterReadLock() / ExitReadLock()

Conclusion

ReaderWriterLock provides synchronized access allowing multiple concurrent readers while ensuring exclusive writer access. However, it's obsolete and should be replaced with ReaderWriterLockSlim for better performance and modern .NET development practices.

Updated on: 2026-03-17T07:04:35+05:30

872 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements