セマフォと有限バッファ問題
第4章 No.2 / 同期処理の中核
スレッドプログラミングで重要な機能が 同期処理 である。その中で重要な要素である 有限バッファ問題 の処理を表すと、以下のようになる。Producer (生産者) は 1 秒ごとに数を生成し、Consumer (消費者) は 2 秒ごとに数を取り出す。バッファの容量は 10。
Sample 12 — Producer / ConsumerJS
Producer の方が速いので、すこしするとバッファが満杯になり、isem (空きスロット数) が 0 になる。すると Producer はブロックして待つ。Consumer が消費すると osem (使用中スロット数) が増えて、再び Producer が動ける。これが セマフォによる同期 である。
class Semaphore {
async Wait() { // カウントを減らし、0 未満なら待つ }
async Signal() { // カウントを増やし、待っている人を起こす }
}
// Producer:
async input(i) {
await isem.Wait(); // 空きスロットを 1 つ確保
buffer[inp++] = i;
osem.Signal(); // 中身が 1 つ増えたと知らせる
}
// Consumer:
async output() {
await osem.Wait(); // 中身を 1 つ確保
const r = buffer[outp++];
isem.Signal(); // 空きが 1 つ増えたと知らせる
return r;
}
同期 / 非同期トグル
最後に、ワイヤーフレームの回転で、同期状態 と 非同期状態 を繰り返すようにした。同期状態では 6 つの回転体がリレー式に 1 つずつ回り、非同期状態では各々勝手に回る。
Sample 13 — Sync / AsyncJS
ソースコード: samples.js 内の ProducerConsumer / Sample13 部分。
おわり