In the solution we present in class, we use two mutex variables. Many of the solutions submitted use one mutex only. A question raised during discussion with a student whether any solution with one mutex is wrong.
I will post some of the solutions submitted by you, and let you take a look and discuss. I think debugging threads is not easy and is a skill that comes with experience. So hopefully this little exercise will serve as a practice for you.
First, I will start off with the correct solution (labelled A) using two mutex variables. The mutex s ensures that only one savage waits at one time.
VERSION A
mutex s, m
cond filled, empty
savage:
while (true)
lock(s)
lock(m)
if (pot is empty)
signal(empty)
wait(filled, m)
eat()
unlock(m)
unlock(s)
cook:
while (true)
lock(m)
if (pot is not empty)
wait(empty, m)
cook()
signal(filled)
unlock(m)
Before we move on to implementations that uses one mutex, here is a slight variable of the above. Here, locking and unlocking of m is done inside the if statement. Is it correct?
VERSION B
mutex s, m
cond filled, empty
savage:
while (true)
lock(s)
if (pot is empty)
lock(m) < --
signal(empty)
wait(filled, m)
unlock(m) <--
eat()
unlock(s)
cook:
while (true)
lock(m)
if (pot is not empty)
wait(empty, m)
cook()
signal(filled)
unlock(m)
Now, here are the four versions of solutions that uses only one mutex.
Version C removes the use of mutex s.
VERSION C
mutex m
cond filled, empty
savage:
while (true)
lock(m)
if (pot is empty)
signal(empty)
wait(filled, m)
eat()
unlock(m)
cook:
while (true)
lock(m)
if (pot is not empty)
wait(empty, m)
cook()
signal(filled)
unlock(m)
Version D replaces signal(filled) with broadcast(filled) in the cook thread.
VERSION D
mutex m
cond filled, empty
savage:
while (true)
lock(m)
if (pot is empty)
signal(empty)
wait(filled, m)
eat()
unlock(m)
cook:
while (true)
lock(m)
if (pot is not empty)
wait(empty, m)
cook()
broadcast(filled) < --
unlock(m)
Version E added a signal(filled) after eat() to VERSION C.
VERSION E
mutex m
cond filled, empty
savage:
while (true)
lock(m)
if (pot is empty)
signal(empty)
wait(filled, m)
eat()
signal(filled) < --
unlock(m)
cook:
while (true)
lock(m)
if (pot is not empty)
wait(empty, m)
cook()
signal(filled)
unlock(m)
Version F changes the if statement to while statement.
VERSION F
mutex m
cond filled, empty
savage:
while (true)
lock(m)
while (pot is empty) < --
signal(empty)
wait(filled, m)
eat()
signal(filled)
unlock(m)
cook:
while (true)
lock(m)
if (pot is not empty)
wait(empty, m)
cook()
signal(filled)
unlock(m)