Skip to content
Dev Dump

🚻 Bathroom Protocol Design

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.
  1. Gender Separation: Males and females cannot use the bathroom simultaneously
  2. Capacity Limit: Maximum of 3 people can use the bathroom at once
  3. Thread Safety: Must handle concurrent access from multiple threads safely
  4. Deadlock Prevention: System must not deadlock under any circumstances
  5. Fair Access: Should provide reasonable access to both genders
  6. Resource Management: Must properly track occupancy and gender

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

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.

  1. Design the state variables: Track current gender and occupancy count
  2. Choose synchronization mechanism: Use ReentrantLock with Condition for efficiency
  3. Implement entry logic: Check gender compatibility and capacity before allowing entry
  4. Handle gender switching: Reset gender when bathroom becomes empty
  5. Implement exit logic: Decrement occupancy and signal waiting threads
  6. Add safety checks: Ensure occupancy never goes negative
  1. Gender switching: Handle when bathroom becomes empty and gender can change
  2. Capacity overflow: Prevent more than 3 people from entering
  3. Concurrent exits: Handle multiple people exiting simultaneously
  4. Thread interruption: Handle InterruptedException properly
  5. Negative occupancy: Prevent occupancy count from going below zero
  6. Gender conflict: Handle when someone tries to enter with wrong gender
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();
}
}
}

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:

  • 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

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 πŸ”’