1. Lock Mechanism
from multiprocessing import Process, Lock
def safe_counter(lock, counter):
with lock:
counter.value += 1
def demonstrate_lock():
from multiprocessing import Value
lock = Lock()
counter = Value('i', 0)
processes = [Process(target=safe_counter, args=(lock, counter)) for _ in range(5)]
for p in processes:
p.start()
for p in processes:
p.join()
2. RLock (Reentrant Lock)
from multiprocessing import RLock
class ThreadSafeCounter:
def __init__(self):
self.lock = RLock()
self._value = 0
def increment(self):
with self.lock:
self._value += 1
self._nested_operation()
def _nested_operation(self):
with self.lock:
## Nested lock is allowed with RLock
print("Nested operation")
Synchronization Primitives Comparison
Primitive |
Use Case |
Blocking |
Reentrant |
Lock |
Basic Mutual Exclusion |
Yes |
No |
RLock |
Nested Locking |
Yes |
Yes |
Semaphore |
Resource Limiting |
Yes |
No |
Event |
Signaling |
No |
N/A |
Advanced Synchronization Techniques
Semaphore Example
from multiprocessing import Semaphore, Process
def worker(semaphore, worker_id):
with semaphore:
print(f"Worker {worker_id} is working")
def demonstrate_semaphore():
## Limit to 3 concurrent processes
semaphore = Semaphore(3)
processes = [
Process(target=worker, args=(semaphore, i))
for i in range(5)
]
for p in processes:
p.start()
for p in processes:
p.join()
Synchronization Flow
graph TD
A[Start Process] --> B{Acquire Lock}
B -->|Success| C[Enter Critical Section]
B -->|Wait| D[Queue for Lock]
C --> E[Modify Shared Resource]
E --> F[Release Lock]
F --> G[Exit Critical Section]
Condition Variable Synchronization
from multiprocessing import Condition, Process
def producer(condition, buffer):
with condition:
buffer.append(item)
condition.notify()
def consumer(condition, buffer):
with condition:
while not buffer:
condition.wait()
item = buffer.pop(0)
LabEx Synchronization Recommendations
At LabEx, we recommend:
- Use the simplest synchronization primitive possible
- Minimize lock duration
- Avoid complex nested synchronization
- Test thoroughly for race conditions
Key Considerations
- Performance overhead
- Deadlock prevention
- Granularity of locking
- Scalability of synchronization mechanism