# Het Synchroniseren van Threads

Eens je het live coderen voldoende onder de knie hebt met een aantal functies en threads tezelfdertijd, dan heb je misschien opgemerkt dat het niet moeilijk is om een fout te maken in één van de threads die dodelijk kan zijn. Niet heel erg, want je kan makkelijk de thread terug herstarten door op afspelen te klikken. Maar als je de thread herstart is deze uit de maat met de originele threads.

## Overgenomen Tijd

Zoals we eerder hebben besproken, erven nieuwe threads gemaakt met `in_thread` alle instellingen van de bovenliggende thread. Dus ook de huidige tijd. Dit betekent dat de threads altijd synchroon met elkaar zijn als zij tegelijkertijd zijn gestart.

Wanneer je een thread op zich start, begint het met zijn eigen klok die waarschijnlijk niet in sync is met een van de andere actieve threads.

## Cue en Sync

Sonic Pi biedt een oplossing voor dit probleem met de functies ‘cue’ en ‘sync’.

‘cue’ laat ons toe, hartslag-berichten te sturen aan alle andere threads. Standaard zijn de andere threads niet geïnteresseerd in deze, en negeren deze hartslag-berichten. Je kan hun aandacht wel vragen met de functie ‘sync’.

Het belangrijkst om weten is dat ‘sync’ vergelijkbaar is met `sleep` in die zin dat het de huidige thread stopt voor een periode van tijd om actief te zijn. Met `sleep` geef je echter aan hoe lang je wilt wachten terwijl je met ‘sync’ niet weet hoe lang je zal wachten - als ‘sync’ op de volgende ‘cue’ van een andere thread wacht die lang of kort kan wegblijven.

Laten we dit in detail bekijken:

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

Hier hebben we twee threads - één gedraagt zich als metronoom, zonder geluid te maken en zend elke maat enkel `:tick` hartslag-berichten uit. De tweede thread synchroniseerd op `tick` berichten en wanneer deze er één ontvangt, erft hij de `cue` tijd thread en blijft lopen.

Als gevolg zullen wij de ‘: drum_heavy_kick’ sample horen, precies op het moment dat de andere thread het `:tick` bericht uitzend, zelfs als de twee threads niet met de uitvoering ervan op hetzelfde moment beginnen:

    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

Die ondeugende `sleep` aanroep zou doorgaans de tweede thread uit fase laten lopen met de éérste. Als we echter `cue` en `sync` gebruiken, synchroniseren we automatisch alle lopende threads die toevallige verschuivingen in timing omzeilen.

## Cue Namen

Je mag eender welke naam gebruiken voor jouw `cue` berichten, niet enkel `:tick`. Je hoeft er alleen voor de zorgen dat alle threads op de correcte naam `sync`-en, anders gaan ze voor eeuwig wachten (of tot je op de stopknopstop klikt tenminste).

Laten we met en paar `cue` namen spelen:

    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

Hier hebben we een hoofd `cue` loop die random de heartbeat namen `:foo`, `:bar` or `:baz`uitzend. We hebben ook drie loop threads die elk onafhankelijk op één van die namen synct en daarbij een verschillende sample afspeeld. Het netto effect is dat we elke 0.5 beat een klank horen als wordt elk van deze 0.5 `sync` threads random ge-synct wordt met de `cue` thread en zijn sample speelt.

Dit werkt natuurlijk ook als jen de threads omgekeerd ordend omdat de`sync` threads gewoon op de volgende `cue` zitten wachten.