セマフォ
emptyCount の初期値は N、fullCount の初期値は0、useQueue の初期値は1である。生産者は次のような処理を繰り返す。
消費者は次のような処理を繰り返す。
具体的には次のような動作をする。
1つの消費者がクリティカルセクションに入る。fullCount は0なので、消費者はブロックする。
いくつかの生産者が生産者側のクリティカルセクションに入る。emptyCount で制限されるのでN以上の生産者はクリティカルセクションに入れない。
生産者は useQueue により一度に1つずつキューにアクセスし、データをキューに入れていく。
最初の生産者がクリティカルセクションを抜けるとき、fullCount がインクリメントされるので、ブロックしていた消費者がクリティカルセクション内の処理に進むことができる。
emptyCount はキュー上の実際の空きスロット数より小さくなる可能性がある。例えば、複数の生産者がデクリメントを行っても、useQueue によってキューへのデータ投入は逐次化されるためである。したがって常に emptyCount + fullCount ≤ N であり、等号が成り立つのは生産者も消費者も全くクリティカルセクションに入っていない場合だけである。
Pythonでは、threadingモジュール中に Semaphoreクラスが用意されている。