# Sincronização de Threads

Quando te tornares suficientemente avançado em live coding com uma serie de funções e threads simultaneamente, irás notar que é bastante fácil fazer em erro num dos threads e o matar. Isso não é muito importante porque o podes reiniciar carregando no Run. No entanto, quando reinicias o thread ele está fora de tempo com os threads originais.

## Herança de tempo

Como discutimos anteriormente, novos threads criados com `in_thread` herdam todas as definições do thread pai. Isto inclui o tempo corrente. Isto significa que os threads estarão sempre sincronizados uns com os outros quando começarem simultaneamente.

No entanto, quando começas um thread por si só, o seu tempo é improvável estar sincronizado com qualquer dos outros threads em execução.

## Fila e sincronização

O Sonic Pi oferece uma solução para este problema com as funções `cue`e `sync`.

`cue`permite-nos enviar uma mensagem de “batimento cardiaco” para todos os outros threads. Por padrão os outro threads não estão interessados na mensagem. No entanto, podes registar interesse com a função `sync`.

A coisa importante a saber é que `sync` é similar a `sleep`na medida que pára o thread corrente de fazer alguma coisa por um período de tempo. No entanto, com `sleep`especificas o tempo de espera enquanto com `sync`não sabes quanto tempo tens de esperar - uma vez que `sync`espera pelo próximo `cue`de outro thread que pode ser logo ou após um longo tempo.

Vamos explorar isto em mais detalhe:

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

Aqui temos 2 threads - um actuando como um metronomo, não tocando nenhum som mas enviando a mensagem de batimento`:tick` a cada beat. O segundo thread está sincronizado na mensagem `tick` e quando recebe um herda o tempo do thread do `cue` e continua a correr.

Como resultado, ouviremos o sample `:drum_heavy_kick` exactamente quando o outro thread envia a mensagem `:tick`, mesmo que o dois threads não começaram o seu tempo de execução ao mesmo tempo:

    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

A chamada maldosa `sleep`tipicamente faria o segundo thread fora de fase com o primeiro. No entanto, como estamos a usar `cue` e `sync`, automaticamente sincronizamos os threads evitando qualquer offset de tempo acidental.

## Nomes de Cues

És livre de usar qualquer nome que queiras para as tuas mensagens de `cue`- não apenas `:tick` . Só tens que assegurar que tal como os outros threads estão `sync`ronizados no nome correcto - ou então ficarão à espera para sempre (ou até carregares no botão Stop).

Vamos jogar com alguns nomes de `cues`:

    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

Aqui temos um `cue` loop principal que está aleatoriamente a enviar um batimento chamado `:foo`,`:bar` ou `:baz`. Temos também 3 loop threads sincronizando a cada um desses nomes independentemente e tocando um sample diferente. O efeito total é que ouvimos um som cada 0.5 batida porque cada `sync`thread é aleatoriamente sincronizado com a thread `cue` e toca o seu sample.

Isto claro que também funciona se inverteres a ordem dos threads pois eles os threads `sync` simplesmente esperam pela próxima `cue`.