Lock.acquire() method in Python's threading module is a fundamental operation to synchronize threads and control access to shared resources. It ensures that only one thread can execute a critical section at a time, preventing race conditions.
Python
import threading
# Create a Lock object
lock = threading.Lock()
shared_counter = 0
def increment():
global shared_counter
# Acquire the lock before entering the critical section
if lock.acquire():
try:
print(f"Lock acquired by {threading.current_thread().name}")
shared_counter += 1 # Critical section
finally:
lock.release() # Ensure the lock is released
print(f"Lock released by {threading.current_thread().name}")
# Create and start multiple threads
threads = []
for i in range(5):
t = threading.Thread(target=increment)
t.start()
threads.append(t)
# Wait for all threads to complete
for t in threads:
t.join()
print(f"Final counter value: {shared_counter}")
Output:
Lock acquired by Thread-17 (increment)
Lock released by Thread-17 (increment)
Lock acquired by Thread-18 (increment)
Lock released by Thread-18 (increment)
Lock acquired by Thread-19 (increment)
Lock released by Thread-19 (increment)
Lock acquired by Thread-20 (increment)
Lock released by Thread-20 (increment)
Lock acquired by Thread-21 (increment)
Lock released by Thread-21 (increment)
Final counter value: 5
Explanation:
- lock.acquire() allows only one thread to enter the critical section.
- shared_counter += 1 is the critical section where shared data is modified.
- lock.release() ensures the lock is released after work is done, even if an error occurs.
Before using acquire(), we need to import the Lock class from the threading module:
from threading import Lock
Lock.acquire() Syntax
lock.acquire(blocking=True, timeout=-1)
Parameters:
blocking (optional):
- True (default): thread waits until the lock becomes available.
- False: thread does not wait; it acquires the lock if it's free, otherwise it moves on.
timeout (optional): Maximum time (in seconds) to wait for the lock.
- -1 (default): Waits indefinitely.
Returns:
- True: Lock was successfully acquired.
- False: Lock was not acquired (when blocking=False or timeout occurs).
Lock.aquire() examples
Example 1: Non-Blocking Acquire
lock.acquire() can be used to attempt acquiring a lock without waiting, allowing threads to proceed only if the lock is available.
Python
lock = threading.Lock() # create lock
def try_lock():
if lock.acquire(blocking=False): # Attempt to acquire the lock without waiting
try:
print(f"Lock acquired by {threading.current_thread().name}")
finally:
lock.release()
print(f"Lock released by {threading.current_thread().name}")
else:
print(f"Lock not acquired by {threading.current_thread().name}")
threads = [threading.Thread(target=try_lock) for _ in range(3)]
for t in threads:
t.start()
for t in threads:
t.join()
Output
Lock acquired by Thread-3 (try_lock)
Lock released by Thread-3 (try_lock)
Lock acquired by Thread-4 (try_lock)
Lock released by Thread-4 (try_lock)
Lock acquired by Thread-5 (try_lock)
Lock released by Thread-5 (try_lock)
Explanation:
- lock.acquire(blocking=False) tries to get the lock without waiting.
- If lock is free, thread enters critical section otherwise, skips it.
- Some threads may fail to acquire the lock if others are already holding it.
Example 2: Acquire with Timeout
lock.acquire() can be used to attempt acquiring a lock for a specific time, allowing threads to wait for the lock but proceed if it is not acquired within the timeout.
Python
import threading
lock = threading.Lock()
def try_lock_with_timeout():
if lock.acquire(timeout=2): # Try to acquire the lock for 2 seconds
try:
print(f"Lock acquired by {threading.current_thread().name}")
finally:
lock.release()
print(f"Lock released by {threading.current_thread().name}")
else:
print(f"Lock not acquired by {threading.current_thread().name}")
threads = [threading.Thread(target=try_lock_with_timeout) for _ in range(3)]
for t in threads:
t.start()
for t in threads:
t.join()
Output
Lock acquired by Thread-14 (try_lock_with_timeout)
Lock released by Thread-14 (try_lock_with_timeout)
Lock acquired by Thread-15 (try_lock_with_timeout)
Lock released by Thread-15 (try_lock_with_timeout)
Lock acquired by Thread-16 (try_lock_with_timeout)
Lock released by Thread-16 (try_lock_with_timeout)
Explanation:
- lock.acquire(timeout=2) waits for up to 2 seconds to acquire the lock.
- Acquires the lock if available within 2 seconds otherwise, moves on.
- Threads either acquire the lock or timeout after 2 seconds.
Best Practices
- Always release the lock after acquiring it (prefer try-finally block).
- Use blocking=False or timeout when immediate access is preferred or long waits are undesirable.
- Avoid deadlocks: Ensure that every acquire() is paired with a release().
Similar Reads
Computer Science Subjects