Unisex Bathroom problem without semaphore Could I ask you to evaluate my solution to Unisex Bathroom Problem?

Problem description


  An office has a bathroom that can be used by both men and women, but not both at the same time. If a man is in the bathroom, other men may enter, but any women wishing to use the bathroom should wait for it to be empty. If a woman is in the bathroom, other women may enter, but any men wishing to use the bathroom should wait it to be empty. Each person (man or woman) will spend some time using the bathroom.


Task


  Design and implement a concurrent solution to the problem. The program should show when a person (man or woman) enters or exits the bathroom; as well as how many people (men or women) are in the bathroom at the moment. Because it is a space of relatively small size, the bathroom has a limiting capacity of persons C (provided as input via the command line or prefixed as a constant value) that can use it at the same time and the time that each person passes in the bathroom is random and different to each program execution.


My solution

I tried to also solve a starvation issue and I think I succeeded.

Besides all of that, what is the necessity of semaphores that the problem is related to? Why can't size be simply compared to capacity as I did?

public class Bathroom {

    private String inUseBy;

    private int size;

    private final int capacity;

    private final Lock lock = new ReentrantLock();

    private final Condition man = lock.newCondition();

    private final Condition woman = lock.newCondition();

    public Bathroom(final int capacity, final int size) {
        this.capacity = capacity;
        this.size = size;
        inUseBy = "";
    }

    public void enter(final String sex) throws InterruptedException {
        lock.lock();
        try {
            while (size == capacity || (size &gt; 0 &amp;&amp; !sex.equals(inUseBy))) {
                if (sex.equals("M")) {
                    man.await();
                } else {
                    woman.await();
                }
            }
            if (size == 0) {
                inUseBy = sex;
            }
            size++;
        } finally {
            lock.unlock();
        }
        System.out.println(sex + " using bathroom. Current employees in bathroom = " + size);
        Thread.sleep(10000);
        System.out.println(sex + " done using bathroom");
        lock.lock();
        try {
            size--;
            if (size == 0) {
                if (sex.equals("M")) {
                    woman.signalAll();
                } else {
                    man.signalAll();
                }
            } else {
                if (sex.equals("M")) {
                    man.signal();
                } else {
                    woman.signal();
                }
            }
        } finally {
            lock.unlock();
        }
    }

}
System.out.println(sex + " using bathroom. Current employees in bathroom = " + size);


This line is not protected by lock, so it is possible that size can change before the output is generated.

For example, if two 'M' arrive simultaneously, you could get as output:

M using bathroom.  Current employees in bathroom = 2
M using bathroom.  Current employees in bathroom = 2


which omits outputting ... = 1.



inUseBy is left as the last occupant, even when size decreases to 0.  In the constructor, it is initialized to "", implying that the empty string might also indicate the bathroom is available to any gender.  When you decrease size to zero, you should clear inUseBy.