π» 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 π