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

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

最終更新:
💡 作る側と使う側を、共有バッファでつなぐ

データを作る生産者と、取り出して処理する消費者が、共有バッファを介して協調する並行処理の問題。容量が有限なら満杯・空の条件を扱い、共有状態を競合なく更新する必要がある。

📌 このページのポイント
作る側と使う側が、バッファを通じて協調する 共有バッファを介して、データを渡す 👨‍🍳 生産者 作って入れる バッファ 🍣 🍣 空 3枠の例 👤 消費者 取って使う 満杯なら 🍣 🍣 🍣 生産者が待つ 空なら □ □ □ 消費者が待つ 共有状態の排他制御 + 空き・データの条件同期 待たずに失敗を返す操作などもある
容量3枠の共有バッファと、必要なら待つ操作の例。矢印はデータの受け渡しの方向。下の2枠は別々の状態で、満杯と空が同時に起きる図ではない。容量や操作によって、待機以外の動作も選べる。
ひよこ ひよこ
生産者-消費者問題って何?
ペンギン先生 ペンギン先生
容量に限りのある回転寿司のレーンを想像してみて。板前さんが寿司を置き、お客さんが取る。満杯なら置く側、空なら取る側が待つ、といった調整が必要だよ。プログラムでは共有バッファへの追加と取り出しを、競合なく行うことも考えるんだ。
ひよこ ひよこ
プログラミングでは、どんな場面に出てくるの?
ペンギン先生 ペンギン先生
たとえば処理依頼をキューへ入れるスレッドと、それを取り出すワーカースレッドを分ける場面だよ。JavaのBlockingQueueにも複数の生産者と消費者の例がある。Webサーバーやログ処理も、そうした構成で設計できるんだ。
ひよこ ひよこ
どうやって同期するの?
ペンギン先生 ペンギン先生
一つの方法は、空き数とデータ数を数えるセマフォに、共有状態を守るロックを組み合わせることだよ。空きやデータを待ってからロックを取る順序が大切。相手が必要とするロックを持ったまま待つと、互いに進めなくなることがあるんだ。
ひよこ ひよこ
もっと簡単に書ける方法はないの?
ペンギン先生 ペンギン先生
Pythonのqueue.QueueやJavaのBlockingQueueなど、同期を内部で扱うキューを使えるよ。ただし操作によって動作は異なる。たとえばJavaのput/takeは必要なら待ち、offer/pollには待たずに失敗を返す形や、時間を区切って待つ形があるんだ。
ひよこ ひよこ
バッファは満杯なら必ず待つもの?
ペンギン先生 ペンギン先生
容量と操作の選び方によるよ。PythonのQueueも、待つ操作のほかに満杯や空を例外で知らせる操作がある。容量を制限しないキューもあるけれど、処理が追いつかなければデータがたまり続ける。満杯時の扱いはシステムの要件に合わせるんだ。
ひよこ ひよこ
サイズはCPUコア数の数倍くらい?
ペンギン先生 ペンギン先生
共通の目安としては決められないよ。データ一件の大きさ、到着の集中、処理速度、許容する待ち時間などによって変わる。容量を増やしても、消費側が継続的に追いつかない問題自体は解消しないので、負荷を測って調整するんだ。
ペンギン
まとめ:ざっくりこれだけ覚えればOK!
「生産者-消費者問題」って出てきたら「作る側と使う側が、共有バッファを通じて協調する並行処理の問題」と思えばだいたいOK!
📖 おまけ:英語の意味
「Producer-Consumer Problem」 = 生産者-消費者問題
💬 Producerは作る側、Consumerは受け取って使う側を表すよ。速度の違う処理同士が、共有バッファを介してやり取りするときの調整を考える問題なんだ。

参考資料

← 用語集にもどる