←Back to Subject
Notes
Notes
Study material and explanations
Diagrams
Diagrams
Visualize concepts easily
Mnemonics
Mnemonics
Tricks to remember faster
One Night Prep
One Night Prep
Short and focused revision
Revision
Revision
Quick summary and key points
Important Questions
Important Questions
Practice most relevant questions
Notes

Thread Synchronization: sleep(), join(), Lock Class & Garbage Collection

Study material and explanations for Unit 5

Thread Methods (sleep, join), Synchronization (Lock) & Garbage Collection

When multiple threads run simultaneously, we need ways to control their timing (sleep() and join()), prevent data corruption (Thread Synchronization using Lock), and understand how Python automatically frees unused memory (Garbage Collection).


1. Thread Control Methods: sleep() and join()

A. The sleep(seconds) Function (time Module)

  • Suspends (pauses) the execution of the currently running thread for a specified number of seconds.
  • While one thread is sleeping, the CPU switches to execute other active threads.

B. The join() Method (Thread Class)

  • When a thread calls t1.join(), the calling thread (usually the Main Thread) pauses and waits until thread t1 finishes its execution completely before moving to the next line of code.
import threading
import time

def download_file():
    print("Download started...")
    time.sleep(2)   # Pauses this thread for 2 seconds
    print("Download completed!")

t1 = threading.Thread(target=download_file)
t1.start()

# Main thread waits here until t1 finishes!
t1.join()
print("Now opening the downloaded file in Main Thread.")

2. Thread Synchronization & Race Condition

What is a Race Condition?

When two or more threads try to modify the same shared resource (like a bank account balance or an available train seat) at the exact same time, the final data becomes corrupted or inconsistent. This bug is called a Race Condition.

What is Thread Synchronization?

Thread Synchronization is the mechanism that ensures only ONE thread can access a shared critical section at a time, preventing Race Conditions.


Synchronization Using the Lock Class (acquire() & release())

Python’s threading module provides the Lock class. A Lock acts like a key to a room:

How Thread Synchronization Works with Lock
1. Acquire Lock
lock.acquire()
(Door Locked 🔒)
→
2. Critical Section
Only 1 Thread Updates Shared Data
→
3. Release Lock
lock.release()
(Door Unlocked 🔓)
  1. lock = threading.Lock(): Creates a new Lock object (initially in the Unlocked state).
  2. lock.acquire(): A thread locks the resource before entering the critical section. If another thread tries to call lock.acquire() at the same time, it is blocked (forced to wait) until the lock is released.
  3. lock.release(): Unlocks the resource after the critical task is done, allowing the next waiting thread to enter.

Example — Ticket Booking with Lock (acquire() & release()):

from threading import Thread, Lock
import time

class TicketCounter:
    def __init__(self, available_seats):
        self.available_seats = available_seats
        self.lock = Lock()  # Create a Lock object

    def book_seat(self, name, seats_requested):
        self.lock.acquire()  # 🔒 Lock acquired: Only 1 thread can enter at a time
        print(f"Checking seats for {name}...")
        
        if self.available_seats >= seats_requested:
            time.sleep(1)
            self.available_seats -= seats_requested
            print(f"SUCCESS: {seats_requested} seat(s) booked for {name}!")
        else:
            print(f"SORRY {name}: Only {self.available_seats} seat(s) left.")
            
        self.lock.release()  # 🔓 Lock released for next waiting thread

counter = TicketCounter(1)  # Only 1 seat available!

# Two users try to book the last 1 seat at the exact same time
t1 = Thread(target=counter.book_seat, args=("Rahul", 1))
t2 = Thread(target=counter.book_seat, args=("Priya", 1))

t1.start()
t2.start()

Output (Safe — No Double Booking!):

Checking seats for Rahul...
SUCCESS: 1 seat(s) booked for Rahul!
Checking seats for Priya...
SORRY Priya: Only 0 seat(s) left.

3. Garbage Collection in Python

In languages like C, programmers must manually allocate and free memory (malloc() and free()). Forgetting to free memory causes Memory Leaks.

Garbage Collection (GC) in Python is an automatic memory management mechanism that finds and deletes objects in RAM that are no longer in use (unreachable), freeing up memory automatically.

How Python’s Garbage Collector Works:

Python uses two techniques together for automatic Garbage Collection:

  1. Reference Counting (Primary Mechanism):
    • Every object in Python keeps a count of how many variables point to it.
    • Whenever a variable is deleted (del x) or reassigned (x = None), the object’s reference count decreases by 1.
    • As soon as an object’s Reference Count reaches 0, Python immediately destroys the object and reclaims its memory!
  2. Generational Garbage Collector (Cycle Detector):
    • Handles Cyclic References (when two objects reference each other in a loop, so their count never hits 0).
    • Python divides objects into 3 Generations (0, 1, 2) and periodically scans them to clean up unused cycles.

Controlling Garbage Collection (gc Module) & Destructor (__del__):

  • __del__(self) (Destructor): A special method called automatically right before Python’s garbage collector destroys an object.
  • gc Module: Allows interacting with the Garbage Collector manually:
    • gc.enable() — Enables automatic garbage collection.
    • gc.disable() — Disables automatic garbage collection.
    • gc.collect() — Forces the Garbage Collector to run immediately and free unused memory.
import gc

class DemoObject:
    def __init__(self):
        print("Object Created in RAM")

    # Destructor called automatically when object is garbage collected
    def __del__(self):
        print("Object Destroyed -> Memory Freed by Garbage Collector!")

obj = DemoObject()
obj = None       # Reference count becomes 0 -> Destructor called immediately!

gc.collect()     # Manually trigger garbage collection cleanup