# スレッドの同期

一度、関数やスレッドを使用したとても高度なライブコーディングを行うと、あるスレッドが止まってしまうような間違いがとても容易に発生することを理解するでしょう。`Run`ボタンを押してスレッドを再スタートさせることは容易にできるので、それは全然大した問題ではないのでしょう。しかし、スレッドを再スタートさせるときは、元々のスレッドと時間がずれることになります。

## 時間の継承

以前話した時に、新しいスレッドが`in_thread`として作られると元のスレッドのすべての設定が継承されることを学びました。これは現在の時間を含んでいます。つまり、スレッドが同時にスタートするときには常に他のスレッドと同期していることを意味しています。

しかし、あるスレッドを独自のタイミングで起動したときは、現在実行中の他のスレッドと同期していることはほとんどないでしょう。

## CueとSync

Sonic Pi は`cue`と`sync`という関数を使ってこの問題の解決方法を提供します。

`cue`はすべての他のスレッドに向けてビートメッセージを送ることができます。初期状態の他のスレッドでは、これらのビートのメッセージは関係付けられず、無視されます。しかし、`sync`関数を使えば、あなたは簡単にこの関連付けを登録することができるのです。

`sync`という機能は、一定の時間、実行中のスレッドを止める`sleep`という関数と非常に似ていることに気づくことが重要です。しかし、`sleep`ではどのくらい休止させるかを決めることができましたが、`sync`ではそれを決めることができず、`sync`は長さに関わらず、次の`cue` が出てくるまで待つのです。

それでは、もうちょっと詳しく見ていきましょう。

    in_thread do
      loop do
        cue :tick
        sleep 1
      end
    end
    in_thread do
      loop do
        sync :tick
        sample :drum_heavy_kick
      end
    end

ここでは2つのスレッドが使われています。1つは、音は鳴りませんがメトロノームのような機能として1秒ごとに`:tick`というビートメッセージを送っています。2つ目のスレッドは、`tick`というビートメッセージと同期し、その際に`cue`のスレッドの時間の情報を継承して実行を続けます。

この結果、`:drum_heavy_kick`のサンプルは、たとえ同時に実行されていない2つのスレッドであったとしても、他のスレッドが`:tick`のメッセージを送信したタイミングで、ぴったりと聴くことができるでしょう。

    in_thread do
      loop do
        cue :tick
        sleep 1
      end
    end
    sleep(0.3)
    in_thread do
      loop do
        sync :tick
        sample :drum_heavy_kick
      end
    end

このちょっとやっかいな`sleep(0.3)`は、1つめのスレッドとは時間がずれた2つめのスレッドを作り出してしまいます。しかしながら、`cue`や`sync`を使えば、タイミングがずれてしまうようなアクシデントを回避してくれます。

## Cueの名前

`cue`には`:tick`以外のどんな好きな名前でも付けられます。その際には他のスレッドと同期させるために必ず正しい名前を使用する必要があります。もし違った場合、永遠に（もしくはストップボタンを押すまで）それは`cue`のメッセージを待ち続けることになります。

それでは`cue`の名前付けを見てみましょう。

    in_thread do
      loop do
        cue [:foo, :bar, :baz].choose
        sleep 0.5
      end
    end
    in_thread do
      loop do
        sync :foo
        sample :elec_beep
      end
    end
    in_thread do
      loop do
        sync :bar
        sample :elec_flip
      end
    end
    in_thread do
      loop do
        sync :baz
        sample :elec_blup
      end
    end

ここではメインの`cue`ループでビートメッセージをランダムに`:foo`と`:bar`、`:baz`に送るようにしています。それから3つのスレッドがそれぞれ独自に同期して、それぞれ異なるサンプルの音を再生します。実際には、`sync`スレッドとして用意した3つのスレッドのいずれかが`cue`スレッドとランダムに同期し、0.5秒毎にサンプル音の再生を聴くことができるでしょう。

逆に`sync`スレッドを単に次の`cue`まで待たせるようにしても、もちろんそれは動作します。