The project is a midification of the solution to project 3 that uses Solaris or POSIX threads, mutexes and condition variables.
I modified project #4 instead of #3.  Compare to the project #4 and project #5, project #5 was much easy to create multiple processes and manipulate them.  In project #4, I needed to consider limited resources of semaphores and shared memory so it was not really easy to code at the first time.  However, in project #5, I did not really need to consider limited resource.

To do project #5, I used the method of Solaris threads as the book described and it was really just a straight conversion as the project described.

I created 3 threads for lieutenant, barber, and sergeant.  Also I created 3 mutexes to control critical sections of threads.  Each thread locks and unlock its own mutex before the thread is executed so we can guarantee that we would not have a race condition problem.

For the lieutenant thread, it will first lock its own mutex and will report the status of the queue and unlock when its process is done.  Also, this thread will check the condition of the barber thread¡¯s mutex.  So, if the barter mutex shows that its thread is done, the lieutenant thread can determine when is time to finish the process.  The other two threads use same strategy as the lieutenant thread use.

Next, the barber thread locks the barber mutex and then, the lieutenant mutex.  After that, the barber thread will process its job.  When the job is done, the thread will unlock the mutex.  When there is no person to be haircut, the barber thread will check the condtiotion of the sergeant mutex whether the sergeant thread is done or not.  If there is no more person to be haircut and the sergeant thread is done, then the barbar thread will finish its process.

The sergeant thread will lock its own mutex first.  The thread will lock the lieutenant mutex before accepting the input and unlock when it has one input.  The sergeant thread will keep accept the input until there is input to execute.  Then the thread will unlock the sergeant mutex and will exit the sergeat thread.

To synchronize use of system resources and performance, a condition variable is the best choice.