Cigarette smokers problem
Assume a cigarette requires three ingredients to smoke:
Assume there are also three chain smokers around a table, each of whom has an infinite supply of one of the three ingredients — one smoker has an infinite supply of tobacco, another has an infinite supply of paper, and the third has an infinite supply of matches.
Assume there is also a non-smoking arbiter. The arbiter enables the smokers to make their cigarettes by arbitrarily (non deterministically) selecting two of the smokers, taking one item out of each of their supplies, and placing the items on the table. The arbiter then notifies the third smoker that they have done this. The third smoker removes the two items from the table and uses them (along with their own supply) to make a cigarette, which they smoke for a while. Meanwhile, the arbiter, seeing the table empty, again chooses two smokers at random and places their items on the table. This process continues forever.
The smokers do not hoard items from the table; a smoker only begins to roll a new cigarette once they have finished smoking the last one. For instance if the arbiter places tobacco and paper on the table while the match-supply smoker is smoking, the tobacco and paper will remain untouched on the table until the match-supply smoker is finished with their cigarette and then collects the items.
Patil's argument was that Edsger Dijkstra's semaphore primitives were limited. He used the cigarette smokers problem to illustrate this point by saying that it cannot be solved with semaphores. However, Patil placed heavy constraints on his argument:
- The agent code is not modifiable.
- The solution is not allowed to use conditional statements or an array of semaphores.
With these two constraints, a solution to the cigarette smokers problem is impossible.
The first restriction makes sense, as Downey says in The Little Book of Semaphores, because if the agent represents an operating system, it would be unreasonable or impossible to modify it every time a new application came along. However, as David Parnas points out, the second restriction makes almost any nontrivial problem impossible to solve:
It is important, however, that such an investigation [of Dijkstra primitives] not investigate the power of these primitives under artificial restrictions. By artificial we mean restrictions which cannot be justified by practical considerations. In this author's opinion, restrictions prohibiting either conditionals or semaphore arrays are artificial. On the other hand, prohibition of "busy waiting" is quite realistic.
If we remove the second of Patil's constraints, the cigarette smokers problem becomes solvable using binary semaphores, or mutexes. Let us define an array of binary semaphores A, one for each smoker; and a binary semaphore for the table, T. Initialize the smokers' semaphores to zero and the table's semaphore to 1. Then the arbiter's code is
while true: time.sleep(T) # choose smokers i and j nondeterministically, # making the third smoker k signal(A[k])
and the code for smoker i is
- Modern Operating Systems (2nd Edition), by Andrew S. Tanenbaum (ISBN 0-13-031358-0)
- The Little Book of Semaphores, by Allen B. Downey, http://greenteapress.com/semaphores
- On a solution to the cigarette smokers' problem without conditional statements, by David Parnas, Communications of the ACM, 18:181-183, March 1975
- Limitations and capabilities of Dijkstra's semaphore primitives for coordination among processes, by Suhas Patil, technical report, MIT, 1971