---
# System prepended metadata

title: Questões de Concorrente

---

# 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()
}



```