Introduction
When many users try to change data at the same time, conflicts can happen that cause errors or lost updates. Lock-based protocols help manage who can access data and when, so changes happen safely and correctly.
Imagine a library where people want to read or write notes in the same book. Shared locks are like allowing several people to read the book quietly, but exclusive locks are like one person writing notes, so others must wait. Two-phase locking is like first gathering all the books you need before starting to read or write, then putting them back only after finishing.
┌───────────────────────────────┐
│ Lock-based Protocols │
├───────────────┬───────────────┤
│ Lock Types │ Two-Phase │
│ │ Locking (2PL) │
│ ┌───────────┐ │ ┌───────────┐ │
│ │ Shared │ │ │ Growing │ │
│ │ Lock │ │ │ Phase │ │
│ └───────────┘ │ ├───────────┤ │
│ ┌───────────┐ │ │ Shrinking │ │
│ │ Exclusive │ │ │ Phase │ │
│ │ Lock │ │ └───────────┘ │
│ └───────────┘ └───────────────┤
├───────────────┬───────────────┤
│ Deadlocks │ Conflict │
│ │ Resolution │
└───────────────┴───────────────┘class LockManager: def __init__(self): self.locks = {} def acquire_shared(self, data_item, transaction): if data_item not in self.locks: self.locks[data_item] = {'shared': set(), 'exclusive': None} lock = self.locks[data_item] if lock['exclusive'] is None or lock['exclusive'] == transaction: lock['shared'].add(transaction) return True return False def acquire_exclusive(self, data_item, transaction): if data_item not in self.locks: self.locks[data_item] = {'shared': set(), 'exclusive': None} lock = self.locks[data_item] if (lock['exclusive'] is None and len(lock['shared']) == 0) or lock['exclusive'] == transaction: lock['exclusive'] = transaction return True return False def release(self, data_item, transaction): if data_item in self.locks: lock = self.locks[data_item] lock['shared'].discard(transaction) if lock['exclusive'] == transaction: lock['exclusive'] = None # Example usage lm = LockManager() print(lm.acquire_shared('x', 'T1')) # True print(lm.acquire_shared('x', 'T2')) # True print(lm.acquire_exclusive('x', 'T3')) # False lm.release('x', 'T1') lm.release('x', 'T2') print(lm.acquire_exclusive('x', 'T3')) # True