The Readers-Writers Problem is a classic synchronization problem in concurrent programming. It involves multiple readers and writers who need to access a shared resource (such as a database or file) while avoiding conflicts.
- Multiple readers can read the shared resource simultaneously.
- Only one writer can write at a time, and no readers should be reading while a writer is writing.
- If a writer is writing, all readers must wait.
We solve this problem using semaphores and mutex locks to manage access to the shared resource.
import threading
import time
import randomthreading: Used for creating multiple threads (readers and writers).time: Simulates delays in reading and writing.random: Introduces randomness in execution to mimic real-world scenarios.
# Semaphore to control writer access (ensures only one writer at a time)
writer_semaphore = threading.Semaphore(1)
# Mutex (lock) to manage the reader count safely
reader_mutex = threading.Lock()
# Shared resource (simulated database or file) and the count of active readers
shared_data = "Initial Data"
reader_count = 0writer_semaphore: Ensures only one writer can write at a time.reader_mutex: Protects thereader_countvariable when multiple readers access it.shared_data: Represents the common resource being read and written.reader_count: Tracks the number of active readers.
def reader(reader_id):
global reader_count
while True:
time.sleep(random.randint(1, 3)) # Simulate random reading intervals
# Entry section: Safely update the reader count
reader_mutex.acquire()
reader_count += 1
if reader_count == 1:
writer_semaphore.acquire() # First reader locks the writer out
print("First reader has started reading, blocking writers.")
reader_mutex.release()
# Critical section: Reading the shared resource
print(f"Reader {reader_id} is reading: {shared_data}")
time.sleep(random.uniform(0.5, 2)) # Simulate time spent reading
# Exit section: Safely update the reader count
reader_mutex.acquire()
reader_count -= 1
if reader_count == 0:
writer_semaphore.release() # Last reader unlocks the writer
print("Last reader has finished reading, allowing writers.")
reader_mutex.release()- Each reader starts after a random delay.
- When the first reader starts reading, it blocks writers using
writer_semaphore.acquire(). - Readers continue reading in parallel.
- When the last reader finishes, it unlocks the writer, allowing writing to resume.
def writer(writer_id):
global shared_data
while True:
time.sleep(random.randint(2, 5)) # Simulate random writing intervals
# Entry section: Gain exclusive access to write
writer_semaphore.acquire()
print(f"Writer {writer_id} has started writing.")
# Critical section: Updating the shared resource
shared_data = f"Updated by Writer {writer_id}"
time.sleep(random.uniform(1, 3)) # Simulate writing time
# Exit section: Release the lock for other writers/readers
print(f"Writer {writer_id} has finished writing.")
writer_semaphore.release()- Writers enter one by one, enforced by
writer_semaphore.acquire(). - They update the
shared_datawhile blocking all readers and writers. - After writing, they release the lock, allowing readers or another writer to proceed.
# Number of reader and writer threads to create
num_readers = 3
num_writers = 2
# Creating reader and writer threads
reader_threads = [threading.Thread(target=reader, args=(i,)) for i in range(num_readers)]
writer_threads = [threading.Thread(target=writer, args=(i,)) for i in range(num_writers)]
# Starting all threads
for t in reader_threads + writer_threads:
t.start()
# Joining all threads (optional, since they run indefinitely)
for t in reader_threads + writer_threads:
t.join()- We create 3 readers and 2 writers.
- Each reader and writer is assigned a thread and started.
- The
.join()ensures threads run indefinitely (can be removed for continuous execution).
The output will vary due to randomness, but it will follow these patterns:
First reader has started reading, blocking writers.
Reader 0 is reading: Initial Data
Reader 1 is reading: Initial Data
Last reader has finished reading, allowing writers.
Writer 0 has started writing.
Writer 0 has finished writing.
First reader has started reading, blocking writers.
Reader 2 is reading: Updated by Writer 0
Last reader has finished reading, allowing writers.
Writer 1 has started writing.
Writer 1 has finished writing.
- Multiple readers can read simultaneously.
- Only one writer can write at a time.
- Readers block writers but not each other.
- The first reader locks out writers, and the last reader unlocks them.
This ensures efficient resource access while maintaining consistency. 🚀