【せいさんしゃしょうひしゃもんだい】

生産者-消費者問題 とは?

💡 回転寿司のレーン――板前が流して客が取る、でもレーンには限りがある!
📌 このページのポイント
生産者-消費者問題 生産者 Producer put バッファ(キュー) D1 D2 D3 データあり 空き get 消費者 Consumer バッファ満杯 → 生産者は待機 バッファ空 → 消費者は待機 排他制御 + 条件同期が必要
生産者-消費者問題のイメージ
ひよこ ひよこ

生産者-消費者問題って何?

ペンギン先生 ペンギン先生

回転寿司をイメージしてみて。板前さん(生産者)がお寿司を作ってレーンに流す。お客さん(消費者)がレーンからお寿司を取る。でもレーンには限りがあるよね。レーンが満杯なら板前さんは待つし、レーンが空ならお客さんは待つ。この調整をどうするかという問題だよ

ひよこ ひよこ

プログラミングだとどういう場面で出てくるの?

ペンギン先生 ペンギン先生

すごく多いよ!Webサーバーがリクエストをキューに入れてワーカースレッドが処理するのも、ログを生成してバッチで書き込むのも、動画のエンコードとアップロードを別スレッドでやるのも、全部生産者-消費者パターンなんだ

ひよこ ひよこ

どうやって実装するの?

ペンギン先生 ペンギン先生

古典的にはセマフォを3つ使うんだ。1つ目はバッファの空きスロット数を管理するセマフォ、2つ目はデータが入っているスロット数を管理するセマフォ、3つ目はバッファへの排他アクセス用のミューテックス。生産者は「空きがある→ロック→データ追加→ロック解放→データありを通知」という流れだよ

ひよこ ひよこ

もっと簡単に書ける方法はないの?

ペンギン先生 ペンギン先生

モニタを使えばもっとシンプルに書けるよ。Javaならwait()とnotify()、Pythonならqueue.Queueを使えば排他制御と条件同期を内部でやってくれるんだ。実務では言語が提供するスレッドセーフなキューを使うのが一般的だよ

ひよこ ひよこ

バッファのサイズってどのくらいにすればいいの?

ペンギン先生 ペンギン先生

これが意外と難しい問題なんだ。大きすぎるとメモリを浪費するし、小さすぎると生産者がすぐブロックされて性能が落ちる。一般的にはCPUコア数の数倍程度が目安だけど、実際にはプロファイリングして調整するよ

ひよこ ひよこ

現代のシステムでも使われているの?

ペンギン先生 ペンギン先生

むしろ現代のほうが重要になっているよ。Apache KafkaRabbitMQなどのメッセージキューはまさに大規模な生産者-消費者パターンだし、Goのchannelもこのパターンを言語レベルでサポートしているんだ

ひよこ ひよこ

古い問題なのに今でも現役なんだね!

ペンギン先生 ペンギン先生

1965年にダイクストラが提唱してから60年以上経つけど、非同期処理マイクロサービスの普及でむしろ重要性が増しているよ。並行プログラミングの基本パターンだから、しっかり理解しておくとシステム設計の引き出しが増えるね

ペンギン
まとめ:ざっくりこれだけ覚えればOK!
生産者-消費者問題って出てきたら「作る側と使う側をバッファで仲介する並行処理の基本パターン」と思えばだいたいOK!
📖 おまけ:英語の意味
「Producer-Consumer Problem」 = 生産者-消費者問題
💬 Producer(生産者)とConsumer(消費者)がバッファを介してやり取りする問題で、1965年にダイクストラが定式化したんだよ
← 用語集にもどる