Bathroom Protocol Design
🧠 Problem Statement
Section titled “🧠 Problem Statement”A bathroom is being designed for shared use by both males and females in an office. The following constraints must be met:
- ❌ Men and women cannot use the bathroom at the same time.
- 🔢 A maximum of 3 employees can use the bathroom simultaneously.
- 🔒 The system must avoid deadlocks.
- ✅ Starvation is not considered in this version.
❗ Constraints
Section titled “❗ Constraints”- Gender Separation: Males and females cannot use the bathroom simultaneously
- Capacity Limit: Maximum of 3 people can use the bathroom at once
- Thread Safety: Must handle concurrent access from multiple threads safely
- Deadlock Prevention: System must not deadlock under any circumstances
- Fair Access: Should provide reasonable access to both genders
- Resource Management: Must properly track occupancy and gender
📥 Input / Output
Section titled “📥 Input / Output”Input:
- Multiple threads representing employees of different genders
- Requests to enter and exit the bathroom
- Gender information for each employee
Output:
- Controlled access to bathroom based on gender and capacity
- Real-time occupancy tracking
- Proper synchronization without deadlocks
💡 Intuition About Solving This Problem
Section titled “💡 Intuition About Solving This Problem”The key insight is that we need to maintain two pieces of state: the current gender using the bathroom and the current occupancy count. We use a single lock to protect both pieces of state and ensure atomic operations. The condition variable allows threads to wait efficiently when the bathroom is unavailable.
🚀 Steps to Take to Solve
Section titled “🚀 Steps to Take to Solve”- Design the state variables: Track current gender and occupancy count
- Choose synchronization mechanism: Use ReentrantLock with Condition for efficiency
- Implement entry logic: Check gender compatibility and capacity before allowing entry
- Handle gender switching: Reset gender when bathroom becomes empty
- Implement exit logic: Decrement occupancy and signal waiting threads
- Add safety checks: Ensure occupancy never goes negative
⚠️ Edge Cases to Consider
Section titled “⚠️ Edge Cases to Consider”- Gender switching: Handle when bathroom becomes empty and gender can change
- Capacity overflow: Prevent more than 3 people from entering
- Concurrent exits: Handle multiple people exiting simultaneously
- Thread interruption: Handle InterruptedException properly
- Negative occupancy: Prevent occupancy count from going below zero
- Gender conflict: Handle when someone tries to enter with wrong gender
💻 Code (with comments)
Section titled “💻 Code (with comments)”import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.ReentrantLock;
public class BathroomAccessControl { private static final int MAX_CAPACITY = 3;
public enum Gender { MALE, FEMALE }
private int occupancy = 0; // Current number of people in bathroom private Gender currentGender = null; // Gender currently using bathroom
private final ReentrantLock lock = new ReentrantLock(); private final Condition bathroomAvailable = lock.newCondition();
public void enterBathroom(Gender gender) throws InterruptedException { lock.lock(); try { // Wait until bathroom is available for this gender while (isBathroomUnavailable(gender)) { bathroomAvailable.await(); }
// If bathroom is empty, set the gender if (occupancy == 0) { currentGender = gender; }
occupancy++; // Increment occupancy count System.out.println(gender + " entered. Current occupancy: " + occupancy); } finally { lock.unlock(); } }
public void exitBathroom() { lock.lock(); try { if (occupancy > 0) { occupancy--; // Decrement occupancy count System.out.println("Person exited. Current occupancy: " + occupancy);
// If bathroom becomes empty, reset gender if (occupancy == 0) { currentGender = null; }
// Signal waiting threads that bathroom is available bathroomAvailable.signalAll(); } } finally { lock.unlock(); } }
private boolean isBathroomUnavailable(Gender gender) { // Bathroom is unavailable if: // 1. At maximum capacity, OR // 2. Different gender is currently using it return occupancy >= MAX_CAPACITY || (currentGender != null && currentGender != gender); }
public int getOccupancy() { lock.lock(); try { return occupancy; } finally { lock.unlock(); } }
public Gender getCurrentGender() { lock.lock(); try { return currentGender; } finally { lock.unlock(); } }}🔍 Dry Run Example
Section titled “🔍 Dry Run Example”Scenario: 2 males and 1 female trying to use bathroom
Initial State:
- Bathroom empty (occupancy = 0, currentGender = null)
Step 1: Male-1 wants to enter
- Check: isBathroomUnavailable(MALE) → false (empty bathroom)
- Set currentGender = MALE
- Increment occupancy to 1
- Male-1 enters bathroom
Step 2: Male-2 wants to enter
- Check: isBathroomUnavailable(MALE) → false (same gender, under capacity)
- Increment occupancy to 2
- Male-2 enters bathroom
Step 3: Female-1 wants to enter
- Check: isBathroomUnavailable(FEMALE) → true (different gender)
- Female-1 waits on bathroomAvailable condition
Step 4: Male-1 exits
- Decrement occupancy to 1
- currentGender remains MALE (bathroom not empty)
- Signal waiting threads
Step 5: Male-2 exits
- Decrement occupancy to 0
- Reset currentGender to null (bathroom now empty)
- Signal waiting threads
Step 6: Female-1 can now enter
- Check: isBathroomUnavailable(FEMALE) → false (empty bathroom)
- Set currentGender = FEMALE
- Increment occupancy to 1
- Female-1 enters bathroom
Result: Gender separation maintained, capacity limit respected, no deadlocks.
⏱️ Time Complexity / Space Complexity
Section titled “⏱️ Time Complexity / Space Complexity”Time Complexity:
- Enter bathroom: O(1) - constant time to check conditions and update state
- Exit bathroom: O(1) - constant time to update state and signal threads
- Wait time: O(1) - constant time to block/unblock threads
Space Complexity:
- State variables: O(1) - constant space for occupancy and gender
- Lock overhead: O(1) - constant space for ReentrantLock and Condition
- Thread management: O(1) - constant space regardless of number of threads
🚻 Usage Example
Section titled “🚻 Usage Example”public class BathroomDemo { public static void main(String[] args) { BathroomAccessControl bathroom = new BathroomAccessControl();
for (int i = 0; i < 5; i++) { createEmployee(bathroom, BathroomAccessControl.Gender.MALE, "Male-" + i); createEmployee(bathroom, BathroomAccessControl.Gender.FEMALE, "Female-" + i); } }
private static void createEmployee(BathroomAccessControl bathroom, BathroomAccessControl.Gender gender, String name) { new Thread(() -> { try { System.out.println(name + " waiting to enter bathroom"); bathroom.enterBathroom(gender); System.out.println(name + " using bathroom"); Thread.sleep((long) (Math.random() * 2000) + 1000); bathroom.exitBathroom(); System.out.println(name + " left bathroom"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }).start(); }}This solution ensures:
- Mutual exclusion of genders 👥
- Bounded occupancy 🚻
- Deadlock-free locking 🔒