# Questões de Concorrente
### Questão 01
###### Fork-sleep-join (3.0)
Crie um programa que recebe um número inteiro n como argumento e cria n goroutines. Cada uma dessas goroutines deve dormir por um tempo aleatório de no máximo 5 segundos. A main-goroutine deve esperar todas as goroutines filhas terminarem de executar para em seguida escrever na saída padrão o valor de n.
```go=
package main
import (
"fmt"
"math/rand"
"time"
)
func printWorking(ch chan int, id int) {
randomNumber := rand.Intn(5)
fmt.Printf("Goroutine %d sleeping for: %d seconds\n", id, randomNumber)
time.Sleep(time.Duration(randomNumber) * time.Second)
ch <- randomNumber
}
func forkSleepJoin(routines int, finishingCh chan int) {
channel := make(chan int)
for i := 1; i <= routines; i++ {
go printWorking(channel, i)
}
for i := 1; i <= routines; i++ {
<-channel
}
fmt.Println("Number of GoRoutines:", routines)
close(finishingCh)
}
func main() {
channel := make(chan int)
forkSleepJoin(5, channel)
<-channel
}
```
### Questão 02
###### two-phase sleep (3.0)
Crie um programa que recebe um número inteiro n como argumento e cria n goroutines. Cada uma dessas goroutines deve dormir por um tempo aleatório de no máximo 5 segundos. Depois que acordar, cada thread deve sortear um outro número aleatório s (entre 0 e 10). **Somente depois** de todas as n goroutines terminarem suas escolhas (ou seja, ao fim da primeira fase), começamos a segunda fase. Nesta segunda fase, a n-ésima goroutine criada deve dormir pelo tempo s escolhido pela goroutine n - 1 (faça a contagem de maneira modular, ou seja, a primeira goroutine dorme conforme o número sorteado pela última).
```go=
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
func createChannels(numberChannels int) []chan int {
var channels []chan int
for i := 0; i < numberChannels; i++ {
channel := make(chan int)
channels = append(channels, channel)
}
return channels
}
var finishingBarrier sync.WaitGroup
var barrier sync.WaitGroup
func main() {
goRoutines := 5
channels := createChannels(goRoutines)
barrier.Add(goRoutines)
finishingBarrier.Add(goRoutines)
for i := 0; i < goRoutines; i++ {
modularIndex := (i + 1) % goRoutines
go execFunc(channels[i], channels[modularIndex])
}
barrier.Wait()
fmt.Println("hum..chegou aqui")
finishingBarrier.Wait()
fmt.Println("Finished!")
}
func execFunc(inCh chan int, outCh chan int) {
firstSleep := rand.Intn(5)
time.Sleep(time.Duration(firstSleep) * time.Second)
randomNumber := rand.Intn(10)
inCh <- randomNumber
fmt.Println("Phase one active! RandomNumber:", randomNumber)
barrier.Done()
barrier.Wait()
fmt.Println("Phase two active!")
sleepTime := <-outCh
time.Sleep(time.Duration(sleepTime) * time.Second)
fmt.Println("Phase two active! Sleep time:", sleepTime)
finishingBarrier.Done()
}
```