セマフォと有限バッファ問題

第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 部分。

おわり