[ Previous: 2.2.2 Cigarette Smokers | Up: 2.2 Classical Problems | Next: 2.3 POSIX Library ]
2.2.3 Unisex Bathroom
Scenario
Have u visited the SOC1 building recently? Not much has changed in the physical structure since SOC relocated to COM1, but a refresher to everyone, there is only one female washroom on the 8th floor. So for all you guys, who get very annoyed that you have to go all the way down to the 3rd floor to use the common room, well SOC, gratefully, has come up with a solution; UNISEX common room!!
Geek 1: Woah!!! Awesome, finally SoC is rocking it.
Geek 2: Yeah lor, we become SCHOOL OF COOLS.
Readers are we getting ideas?
Did it invoke thoughts of perhaps arranging a meeting with a special someone, when you are up all night coding?
Or did your creative side get the better of you, and you commenced planning on an intricate, artistic and clever plan to get someone to notice you?
Which would eventually lead to something like this?
Take our advice, pause all those thoughts!!
Geek 1: Wah wah, what and why??
Geek 2: Yeah, why? I was in such a nice place, a natural high. :(
Yeah well, I was equally disappointed.
We are not in the school of computing for no reason. The smart professors at SOC have devised a devious plan, such that people from the opposite sex can not use the washroom at same time.
Geek 1 & Geek 2: (Wailing)!!
So to put things in perspective we have the following situation:
- There cannot be men and women at the same time in the bathroom.
- There are n number of cubicles.
As students of CS2106, you would realize that the problem could be sorted out, with the aid of semaphores. But potential problems that could arise are deadlock and starvation.
Well we would deal with that in time. For now, lets get started by trying to prevent members of the opposite sex to mingle in the common room.
Solution
- Semaphores
- Bathroom is the shared resource
- Male and Females would acts as threads
Problems
Problems that arise as a result of the implementation of this protocol are:
- Deadlock – This situation would arise, when all individuals who waiting to use the common room, never get to. This could arise as result of improper software implementation of the semaphores. Theoretically, since there are n(at least 1) cubicles, one person would get to use it, and deadlock would not occur.
- Denial/Starvation – Since it’s a condition that we have one party being denied the access of resources. In this case the resource being the washroom. For example, we could have a situation, where there a whole line of women and just one man, waiting to use the common room. In this case, women would always be using up the n cubicles, and it would take a very long time before the gent would get an opportunity, because he would be unable to use it unless all n cubicles are free, due the no gender mixing policy.
Use of Semaphores
The solution involves the use of semaphores as mentioned earlier.
- Let us assume that there are 3 cubicles, i.e n = 3
- femaleMultiplex – this semaphore would be initialized to 3 (n). This would control the number of women in (making sure not more than 3).
- maleMultiplex – similar function as for the femaleMultiplex, whoever applicable to males
- Empty – is a mutex, it is 1 if room empty, 0 otherwise
- nextInLine – is a mutex, if the sex of the person is different from the group/person inside it is 0, 1 otherwise
- maleSwitch – LightSwitch() allows men to bar women from the room. When the first male enters, the lightswitch locks empty, barring women; When the last male exits,
it unlocks empty, allowing women to enter
- femaleSwitch – LightSwitch(), Women do likewise using the same
Procedure #1 (Non-Solution)
- When a person (assume female) arrives, and if there is no one in the bathroom, she would be allowed to enter.
- At this point femaleSwitch.lock(empty) would be called. This would bar men from accessing the bathroom.
- Then femaleMultiplex.wait() or P() would be called to decrease the semaphore of the females. (At wait(), it checks if there are vacancies, and only if there are any it proceeds.)
- If the bathroom is operating at maximum capacity then the female thread would wait until a vacancy opens up!
- Once the female (thread) is ready to leave, the thread would first increment the value in the femaleMultiplex semaphore, by calling femaleMultiplex.signal() or V().
- Now suppose, another female in queue wanted to enter, the thread too would follow the same steps as above.
- When the number of femaleMultiplex is 3 (n), that implies the bathroom is empty, at which point, femalSwitch.unlock(empty) is carried out. Every thread reads femaleSwtich.unlock(empty), however, it is unlocked only when the semaphore value is equal to maximum number of cubicles. (Although in theory, there is no operation to get the value of a semaphore, the library for semaphore implementation may have such a function. Even if it is not available, we can use a simple counter to keep track of the semaphore value manually.)
- This would notify that the bathroom is empty and would not bar men from entering.
The pseudo code for the above, female version (similar version for males, using male variables) is as follows:
femaleSwitch.lock(empty)
femaleMultiplex.wait()
# bathroom code here
femaleMultiplex.signal()
femaleSwitch.unlock(empty)
The problem with above solution is that the situation could go into a state of starvation. That is there could be a long line of females, and just one man, waiting. In which, case the male would not get a chance for a very long and unfair period of time, even though he might have been there before many females. This is because, in the above code we check the gender of the people in the bathroom, and allow a maximum number of individuals of the particular sex to go in until the bathroom is completely empty.
So, a solution to the above problem is implementing nextInLine. This would check who is in queue next and would bar the thread if it is of the opposite nature the thread currently being processed.
nextInLine – is a mutex, if the sex of the person (the thread) is different from the group/person inside it is 0, 1 otherwise.
Procedure #2 (Solution)
- We have a nextInLine mutex, which would check the incoming thread, i.e it would perform a nextInLine.wait()
- And bar a thread of the different nature to what is being currently processed.
- For example: suppose the room is currently with males, but next thread if female. Then nextInLine would block the female thread, and wait until all male threads have finished. Then the female thread would be allowed to enter.
- After the female thread gets through nextInLine.wait() (which means the female enters the bathroom), the thread would call femaleSwitch.lock(empty), which bars males from entering.
- When exiting after using the bathroom (thread executes respective code), in the case where a female thread is waiting on existing male threads to finish utilizing the resource, the maleSwitch.unlock(empty) would check the male semaphore variable to ensure its equal to 3 (n number of cubicles), and signal that the bathroom is empty.
- Women would be allowed to enter to n capacity (as in procedure 1), until the next male arrives. Then the process repeats itself.
So in this manner starvation would be avoided. This procedure may not be efficient. This system could perhaps be implemented in a system with several hundred threads. If there is a frequent change in the type (gender) of thread, then it would be blocked and hence barring additional threads.
The pseudo code for the above procedure (for the male thread) is:
nextInLine.wait()
maleSwitch.lock(empty)
nextInLine.signal()
maleMultiplex.wait()
# bathroom code here
maleMultiplex.signal()
maleSwitch.unlock(empty)
Procedure #3 (Efficiency vs Fairness)
The following solution is what we think can be an improvement in efficiency over the previous one.
- We could implement 2 queues, one for males and the other for females.
- Queuing numbers are given to each thread that arrives on a first come first serve basis.
- That is, in queue F (female), I could have numbers 1, 2, 4-10. And in queue M (male), numbers 3, 8, 11.
- Suppose initially the bathroom is empty. So the first thread is a female, therefore, females would be allowed to enter to maximum capacity, in this case 3.
- Now when reading sequence numbers, since it is sequential (successor is +1 of the predecessor), there would be a hiccup after 2 in the female queue, as 3 is not there. This would mean that there are males waiting.
- However, instead of just letting 1 & 2 to enter, and then swapping to 3 (male queue) as would have been done in procedure 2, it is noted that a jump in sequence number has occurred, which is a sign to visit the male queue.
- Three (maximum capacity of bathroom) females would be allowed to enter, i.e. 1, 2 & 4. Then female threads are barred. The male thread 3 would be blocked.
- Once the threads 1, 2 & 4 have finished, thread 3 would be allowed to enter.
- Here again after 3, there is a jump, it is noted. Therefore, it would permit the next 2 in queue to enter, and then bar further male threads.
- Once again, we would swap to the female queue.
The above procedure minimizes the number of swapping, as compared to procedure 2. It ensures that the bathroom always runs at full capacity, for either of the sex as long as there are people in the queue. Although threads are not entered in sequence order, it is obvious that the efficiency offsets the slight unfairness.
The pseudo code is similar to procedure 2:
// nextInLine checks for sequence number, in addition. If a jump is noted, it would adjust a variable, say unfair = (n - currentlyInside). Hence, that many from the current queue would be allowed, before being barred. After unfair amount have entered, the threads from the other queue would be allowed to enter.
nextInLine.wait() // checks for sequence number, in addition
maleSwitch.lock(empty)
nextInLine.signal()
maleMultiplex.wait()
# bathroom code here
maleMultiplex.signal()
maleSwitch.unlock(empty)
References
1. Allen B. Downey (2005),
The Little Book of Semaphores
2. David J. Powers (2006),
The Unisex Bathroom: Fairness versus Performance
[ Previous: 2.2.2 Cigarette Smokers | Up: 2.2 Classical Problems | Next: 2.3 POSIX Library ]