Reader-Writer Locks in C# β The Smart Way to Handle Threads!
Hey there, C# hero! π Have you ever wondered how multiple threads can read shared data safely while ensuring that only one thread can write at a time?
That’s exactly what Reader-Writer Locks in C# do! π
Today, we’ll break them down in a super friendly way with real-world examples and easy-to-follow code. Letβs go! π‘
π What You Are Going to Learn in This Lesson?
βοΈ What are Reader-Writer Locks in C#?
βοΈ Why are they important for thread synchronization?
βοΈ How to use ReaderWriterLockSlim
in a simple program?
βοΈ Real-world scenarios where they shine!
π€ Why Do We Need Reader-Writer Locks?
Imagine this:
- You are in a library π. Many people can read books at the same time.
- But if someone wants to write in a book, they need exclusive access.
This is exactly how Reader-Writer Locks in Thread work!
π‘ Multiple threads can read at the same time, but only one thread can write while blocking others.
π What is ReaderWriterLockSlim?
ReaderWriterLockSlim
is a built-in class in C# that helps optimize read-heavy operations by allowing:
β‘οΈ Multiple readers to access the resource simultaneously.
β‘οΈ Only one writer to modify the resource at a time.
β‘οΈ No readers are allowed when a writer is active.
Β
β Syntax of ReaderWriterLockSlim
ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
π Example 1: Basic Reader-Writer Lock in Thread
Letβs see how multiple readers can access data at the same time, but only one writer can update it.
using System;
using System.Threading;
class Program
{
static ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
static int sharedData = 0;
static void Reader()
{
rwLock.EnterReadLock(); // Acquire read lock
Console.WriteLine($"Reader {Thread.CurrentThread.ManagedThreadId} reads value: {sharedData}");
Thread.Sleep(1000);
rwLock.ExitReadLock(); // Release read lock
}
static void Writer()
{
rwLock.EnterWriteLock(); // Acquire write lock
sharedData++;
Console.WriteLine($"Writer {Thread.CurrentThread.ManagedThreadId} updated value to: {sharedData}");
Thread.Sleep(1000);
rwLock.ExitWriteLock(); // Release write lock
}
static void Main()
{
for (int i = 0; i < 3; i++) new Thread(Reader).Start();
Thread.Sleep(500); // Ensure readers start first
new Thread(Writer).Start();
}
}
β Expected Output
Reader 3 reads value: 0
Reader 4 reads value: 0
Reader 5 reads value: 0
Writer 6 updated value to: 1
- Multiple readers read the value at the same time.
- The writer waits until all readers are done, then updates the value.
π― Why is ReaderWriterLockSlim Important?
- Better Performance β It allows multiple readers instead of blocking all threads.
- Ensures Thread Safety β Prevents data corruption.
- Useful in Read-Heavy Applications β Like databases, logging systems, or caching.
π Example 2: Preventing Race Conditions with Reader-Writer Locks in Thread
Letβs simulate a race condition and fix it with ReaderWriterLockSlim
.
using System;
using System.Threading;
class Program
{
static ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
static int counter = 0;
static void IncrementCounter()
{
rwLock.EnterWriteLock();
counter++;
Console.WriteLine($"Counter updated to {counter} by Thread {Thread.CurrentThread.ManagedThreadId}");
rwLock.ExitWriteLock();
}
static void ReadCounter()
{
rwLock.EnterReadLock();
Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} read counter: {counter}");
rwLock.ExitReadLock();
}
static void Main()
{
for (int i = 0; i < 3; i++) new Thread(ReadCounter).Start();
new Thread(IncrementCounter).Start();
}
}
β Expected Output
Thread 3 read counter: 0
Thread 4 read counter: 0
Thread 5 read counter: 0
Counter updated to 1 by Thread 6
Before the writer modifies the value, readers safely access it.
π Real-World Example: Online Banking System
Imagine an online banking system.
- Multiple users check their account balance (readers).
- Only one user can update the balance at a time (writer).
Β
β Code for Real-World Example
using System;
using System.Threading;
class BankAccount
{
static ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
static int balance = 1000;
static void CheckBalance()
{
rwLock.EnterReadLock();
Console.WriteLine($"User {Thread.CurrentThread.ManagedThreadId} checked balance: ${balance}");
Thread.Sleep(500);
rwLock.ExitReadLock();
}
static void WithdrawMoney(int amount)
{
rwLock.EnterWriteLock();
if (balance >= amount)
{
balance -= amount;
Console.WriteLine($"User {Thread.CurrentThread.ManagedThreadId} withdrew ${amount}. New balance: ${balance}");
}
else
{
Console.WriteLine($"User {Thread.CurrentThread.ManagedThreadId} tried to withdraw ${amount}, but insufficient funds.");
}
rwLock.ExitWriteLock();
}
static void Main()
{
new Thread(CheckBalance).Start();
new Thread(CheckBalance).Start();
new Thread(() => WithdrawMoney(500)).Start();
new Thread(CheckBalance).Start();
}
}
β Expected Output
User 3 checked balance: $1000
User 4 checked balance: $1000
User 5 withdrew $500. New balance: $500
User 6 checked balance: $500
- Multiple users check their balance at the same time.
- Only one user withdraws money, ensuring accuracy.
π Key Takeaways
β
ReaderWriterLockSlim allows multiple readers but only one writer.
β
Prevents race conditions in read-heavy applications.
β
Use in real-world cases like banking, logging, caching, and database operations.
Β
π Next What?
π Awesome job! You now understand Reader-Writer Locks in C# and how they improve thread safety.
But what if we need collections that are thread-safe? π€
π₯ Next up: Thread-Safe Collections in C# β Keep Data Safe in Multithreading! Stay tuned! π