C# ReaderWriterLockSlim Class
Last Updated :
28 Apr, 2025
In C#, the ReaderWriterLockSlim class is present in the System.Threading namespace which is used to provide synchronization in a multithreaded environment. It allows multiple threads to read the resource concurrently, but only one thread can write at a time
Key Features:
- More flexibility and optimization than the traditional ReaderWriterLock.
- It is easy to use with recursion, simplifies the lock for reading or writing multiple times, and handles the possible deadlock conditions internally.
- Provide an easier mechanism for upgrading and downgrading Locks.
Example: Use of ReaderWriterLockSlim to update the shared resource in a multithreaded environment.
C#
// Using ReaderWriterLockSlim in C#
using System;
using System.Threading;
class Geeks
{
private static ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
private static string res = "Initial Value";
public static void Main()
{
Thread write = new Thread(Writer);
Thread read1 = new Thread(Reader);
Thread read = new Thread(Reader);
write.Start();
read1.Start();
read.Start();
write.Join();
read1.Join();
read.Join();
}
private static void Writer()
{
rwLock.EnterWriteLock();
try
{
res = "Value is updated";
Thread.Sleep(200);
Console.WriteLine("Performed written operation.");
}
finally
{
rwLock.ExitWriteLock();
}
}
private static void Reader()
{
rwLock.EnterReadLock();
try
{
Console.WriteLine("Shared Resource: " + res);
Thread.Sleep(100);
}
finally
{
rwLock.ExitReadLock();
}
}
}
OutputPerformed written operation.
Shared Resource: Value is updated
Shared Resource: Value is updated
Explanation: In the above example, we use ReaderWriterLockSlim to perform read and write operations on the shared resource. We create two threads which perform the reading operation and one thread is performing the writing operation on the shared resource.
Constructor
Constructor | Description |
---|
ReaderWriterLockSlim() | This constructor creates a new instance of the ReaderWriterLockSlim class without the recursion. |
---|
ReaderWriterLockSlim(LockRecursionPolicy recursionPolicy) | This constructor creates a new ReaderWriterLockSlim with the specified recursion policy. |
---|
Example: Initializing the ReaderWriterLockSlim with the ReaderWriterLockSlim(LockRecursionPolicy) constructor.
C#
// Initializing the ReaderWriterLockslim
// With the ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion)
using System;
using System.Threading;
public class Geeks
{
// Create a ReaderWriterLockSlim with recursion policy set to SupportsRecursion
private static ReaderWriterLockSlim Lock =
new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
// Shared resource to be read and written
// Initial value is set to 0
private static int c = 0;
// Method to read the shared resource
public static void ReadResource()
{
Lock.EnterReadLock();
try
{
Console.WriteLine("Reading resource: " + c);
}
finally
{
Lock.ExitReadLock();
}
}
// Method to write to the shared resource
public static void WriteResource(int newValue)
{
Lock.EnterWriteLock();
try
{
Console.WriteLine("Writing resource: " + newValue);
c = newValue;
}
finally
{
Lock.ExitWriteLock();
}
}
// Reader method that calls itself recursively
public static void RecursiveRead(int count)
{
if (count > 0)
{
Lock.EnterReadLock();
try
{
Console.WriteLine($"Recursively reading resource, count = {count}: " + c);
// Call the method recursively
RecursiveRead(count - 1);
}
finally
{
Lock.ExitReadLock();
}
}
}
public static void Main()
{
// Writing initial value to shared resource
WriteResource(100);
// Start multiple threads to simulate reading and recursion
Thread read1 = new Thread(() => ReadResource());
Thread read2 = new Thread(() => RecursiveRead(2));
read1.Start();
read2.Start();
read1.Join();
read2.Join();
// Writing new value to
// shared resource
WriteResource(200);
}
}
OutputWriting resource: 100
Reading resource: 100
Recursively reading resource, count = 2: 100
Recursively reading resource, count = 1: 100
Writing resource: 200
Explanation: In the above example, we initialize a ReaderWriterLockSlim with the constructor ReaderWriterLockSlim(LockRecursionPolicy recursionPolicy) which allows to use of lock recursively here we create a thread which is used to read the shared resource recursively.
Properties
Property | Description |
---|
IsReadLockHeld | This property checks whether the current thread holds a read lock or not. |
---|
IsUpgradeableReadLockHeld | It is used to check whether the current thread holds an upgradeable read lock or not. |
---|
IsWriteLockHeld | It is used to check the current thread holds a write lock. |
---|
RecursionPolicy | It is used to retrieve the recursion policy for the lock And check the lock can be reacquired recursively. |
---|
CurrentReadCount | Used to retrieve the number of threads that presently hold a read lock. |
---|
RecursiveReadCount | It returns the number of times the current thread has entered the read lock in recursion. |
---|
RecursiveUpgradeCount | This property is used to retrieve the number of times the current thread has entered the upgradeable read lock in recursive mode. |
---|
RecursiveWriteCount | It is used to retrieve the number of times the current thread has entered the write lock in recursive mode. |
---|
WaitingReadCount | Used to retrieve the number of threads which are currently waiting to enter the read lock. |
---|
WaitingUpgradeCount | This property retrieves the number of threads which are currently waiting to enter the upgradeable read lock. |
---|
WaitingWriteCount | This property is used to check the count of the number of threads that are waiting to enter the write lock. |
---|
Example: Using the IsReaderLockHeld and IsWriterLockHeld properties to check the lock's status during execution.
C#
using System;
using System.Threading;
class Geeks
{
// Shared resource
private static int val = 0;
// Creating the ReaderWriterLockSlim object
private static ReaderWriterLockSlim rwLock =
new ReaderWriterLockSlim();
// Read operation
public static void Read()
{
// Entering the read lock
rwLock.EnterReadLock();
try
{
// Accessing shared resource (counter)
Console.WriteLine($"Reader Thread {Thread.CurrentThread.ManagedThreadId} reading counter: {val}");
}
finally
{
// Releasing the read lock
rwLock.ExitReadLock();
}
}
// Write operation
public static void Write(int value)
{
// Entering the write lock (exclusive access)
rwLock.EnterWriteLock();
try
{
// Modifying shared resource (val)
val = value;
Console.WriteLine($"Writer Thread {Thread.CurrentThread.ManagedThreadId} updated counter to: {val}");
}
finally
{
// Releasing the write lock
rwLock.ExitWriteLock();
}
}
public static void Main()
{
// Creating reader threads
Thread read = new Thread(Read);
Thread read2 = new Thread(Read);
Thread read3 = new Thread(Read);
// Creating writer thread
Thread write = new Thread(() => Write(3));
// Starting threads
read.Start();
read2.Start();
read3.Start();
write.Start();
// Waiting for all threads to finish
read.Join();
read2.Join();
read3.Join();
write.Join();
// Checking lock status after the operations
Console.WriteLine($"IsReaderLockHeld: {rwLock.IsReadLockHeld}");
Console.WriteLine($"IsWriterLockHeld: {rwLock.IsWriteLockHeld}");
}
}
OutputWriter Thread 6 updated counter to: 3
Reader Thread 4 reading counter: 3
Reader Thread 5 reading counter: 3
Reader Thread 3 reading counter: 3
IsReaderLockHeld: False
IsWriterLockHeld: False
Explanation: In the above example, we use the ReadWriterLockSlim class properties like IsReaderLockHeld which is used to check whether the status of the lock is completed or not, the output may be different each time because we are performing the multithreaded operations.
Methods
Method | Description |
---|
EnterReadLock() | This method is used to read the lock or block if necessary until the lock is available for the required. |
---|
TryEnterReadLock(TimeSpan timeout) | This method tries to acquire a read lock and we can specify a timeout period in the argument. |
---|
TryEnterReadLock(int millisecondsTimeout) | It is used to try to acquire a read lock within we can also specify the timeout timings in the argument in milliseconds. |
---|
EnterWriteLock() | This method takes a write lock, blocking if necessary until the lock is available. |
---|
TryEnterWriteLock(TimeSpan timeout) | This method acquires a write lock within the specified timeout period which we passed on the argument in milliseconds. If the lock cannot be acquired within the given time, it returns false. |
---|
TryEnterWriteLock(int millisecondsTimeout) | It tries to acquire a write lock in the specified timeout period in the argument in milliseconds. If the lock cannot be acquired within the given time, it returns false. |
---|
EnterUpgradeableReadLock() | This method takes control over the upgradeable read lock, Awaiting the lock acquisition. |
---|
TryEnterUpgradeableReadLock(TimeSpan timeout) | This method is used to take control over an upgradeable read lock within the specified timeout period. |
---|
TryEnterUpgradeableReadLock(int millisecondsTimeout) | Use to take control over an upgradeable read lock within the specified timeout period in milliseconds. If the lock cannot be acquired within the given time, it returns false. |
---|
ExitReadLock() | This method is used to free a read lock held by the current thread. |
---|
ExitWriteLock() | It is used to free a write lock which is held by the current thread. |
---|
ExitUpgradeableReadLock() | This method is used to release the upgradeable read lock held by the current thread. |
---|
Dispose() | It is used to free all resources used when the lock is no longer needed, to ensure that system resources are freed up. |
---|
Example: Using EnterReadLock(), TryEnterReadLock(int millisecondsTimeout), and EnterWriteLock() from the ReaderWriterLockSlim class.
C#
// Using methods of ReaderWriterLockSlim class in C#
using System;
using System.Threading;
class Geeks
{
// Shared resource
private static int res = 0;
// Create ReaderWriterLockSlim instance
private static ReaderWriterLockSlim rwLock =
new ReaderWriterLockSlim();
// Method for reading
public static void Read()
{
try
{
// Acquiring a read lock
rwLock.EnterReadLock();
Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} reading counter: {res}");
}
finally
{
// Releasing the read lock
rwLock.ExitReadLock();
}
}
// Method for trying to acquire read lock
// With a timeout (using TryEnterReadLock)
public static void TryReadWithTimeout()
{
// Attempting to acquire the read lock with 500ms timeout
if (rwLock.TryEnterReadLock(500))
{
try
{
Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} successfully acquired read lock.");
Console.WriteLine($"Counter value: {res}");
}
finally
{
rwLock.ExitReadLock();
}
}
else
{
Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} could not acquire read lock within timeout.");
}
}
// Method for writing (using EnterWriteLock)
public static void Write()
{
try
{
// Acquiring a write lock
rwLock.EnterWriteLock();
res++;
Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} updated counter to: {res}");
}
finally
{
// Releasing the write lock
rwLock.ExitWriteLock();
}
}
public static void Main()
{
// Create and start threads for reading and writing
Thread read1 = new Thread(Read);
Thread read2 = new Thread(TryReadWithTimeout);
Thread write = new Thread(Write);
read1.Start();
read2.Start();
write.Start();
read1.Join();
read2.Join();
write.Join();
}
}
OutputThread 5 updated counter to: 1
Thread 3 reading counter: 1
Thread 4 successfully acquired read lock.
Counter value: 1
Explanation: In the above example, we use EnterReadLock() method blocks until the read lock is available. It acquires the lock for the specified time which we pass 500 milliseconds and if it does not acquire the lock on the specified time then it will show the error message. And read the shared resource then we use the EnterWriteLock() which acquires the write lock updates the shared resource and then releases the lock.
Note: ReaderWriterLockSlim is not thread-abort safe. If threads accessing it can be aborted. The abort method is also obsoluted in the newer .NET versions.
Similar Reads
C# - FileInfo Class Methods
In this article, we will explain the FileInfo class, its methods, properties, etc. The System.IO namespace is one of the most important namespaces we used while we are working with files in C#. FileInfo Class:It does not have static methods and it can only be used on instantiated objects. The class
3 min read
C# Binary Writer
Pre-requisites: Introduction to C# C# is a general-purpose, modern and object-oriented programming language pronounced as âC Sharpâ. It was developed by Microsoft led by Anders Hejlsberg. In C# Binary Writer is a class that is used to write primitive types as binary data in particular encoding strea
3 min read
How to Read and Write a Text File in C#?
Termination of a program leads to the deletion of all data related to it. Therefore, we need to store the data somewhere. Files are used for permanently storing and sharing data. C# can be used to retrieve and manipulate data stored in text files. Reading a Text file: The file class in C# defines tw
5 min read
How to Use C# BinaryWriter Class?
In this article, we will illustrate a binary writer in C#. Following are some important points regarding Binary Writer: Binary Writer is used to generating binary files.Strings can be written in specific encoding using Binary Writer.Binary Writer constructor takes an object of type Stream to create
4 min read
File.OpenWrite() Method in C# with Examples
File.OpenWrite(String) is an inbuilt File class method that is used to open an existing file or creates a new file for writing. Syntax:Â public static System.IO.FileStream OpenWrite (string path); Parameter: This function accepts a parameter which is illustrated below:Â path: This is the specified t
3 min read
File.CreateText() Method in C# with Examples
File.CreateText() is an inbuilt File class method that is used to overwrite the contents of the existing file with the given UTF-8 encoded text and if the file is not created already, this function will create a new file with the specified contents. Syntax:Â public static System.IO.StreamWriter Crea
3 min read
File.SetLastWriteTime() Method in C# with Examples
File.SetLastWriteTime(String) is an inbuilt File class method which is used to set the date and time that the specified file was last written to. Syntax:  public static void SetLastWriteTime (string path, DateTime lastWriteTime); Parameter: This function accepts two parameters which are illustrate
3 min read
File.WriteAllBytes() Method in C# with Examples
File.WriteAllBytes(String) is an inbuilt File class method that is used to create a new file then writes the specified byte array to the file and then closes the file. If the target file already exists, it is overwritten. Syntax:  public static void WriteAllBytes (string path, byte[] bytes); Param
3 min read
How to Thread Lock Work in C#?
C# makes the concurrent execution of a code possible with the help of threads. The namespace System. Threading which is pre-built in C# supports the use of threads. Typically we create threads for the concurrent execution of a program. But in certain cases we may not want our program to be run concu
4 min read
Implementing Binary Reader Using C#
BinaryReader is a class that is present under the System.IO namespace. This is used for handling the binary values from a particular encoding stream. Syntax: This will create the BinaryReader object for a particular input stream by using UTF-8 encoding. BinaryReader br = new BinaryReader(Stream) Thi
2 min read