diff --git a/cmd/aprendago/main.go b/cmd/aprendago/main.go index 66ad948..5bee968 100644 --- a/cmd/aprendago/main.go +++ b/cmd/aprendago/main.go @@ -1,4 +1,12 @@ -// Aprenda Go: https://youtube.com/playlist?list=PLCKpcjBB_VlBsxJ9IseNxFllf-UFEXOdg&si=_JIbmByhwYvHdJAr +/* +Main function to start the application and call the menu options based on the arguments +passed by the user. +If no arguments are passed, the HelpMe function is called to show the available options. +If arguments are passed, the Options function is called to execute the requested option. + - os.Args[1:] is used to pass all arguments except the first one, which is the name of the program. + This way, the Options function receives only the arguments that are relevant to the requested option. + For example, if the user types "--outline", the Options function will receive only "--outline". +*/ package main import ( diff --git a/internal/concorrencia/overview.yml b/internal/concorrencia/overview.yml new file mode 100644 index 0000000..39fd04e --- /dev/null +++ b/internal/concorrencia/overview.yml @@ -0,0 +1,81 @@ +--- +description: + name: "Capítulo 18: Concorrência" + sections: + - title: "Concorrência vs Paralelismo" + text: | + - Concorrência é quando abre uma padaria do lado da outra e as duas quebram :) + - Fun facts: + - O primeiro CPU dual core "popular" veio em 2006 + - Em 2007 o Google começou a criar a linguagem Go para utilizar essa vantagem + - Go foi a primeira linguagem criada com multi-cores em mente + - C, C++, C#, Java, JavaScript, Python, etc., foram todas criadas antes de 2006 + - Ou seja, Go tem uma abordagem única (fácil!) para este tópico + - E qual a diferença entre concorrência e paralelismo? + + - title: "Goroutines & WaitGroups" + text: | + - O código abaixo é linear. Como fazer as duas funções rodarem concorrentemente? + - https://play.golang.org/p/XP-ZMeHUk4 + - Goroutines! + - O que são goroutines? São "threads." + - O que são threads? [WP](https://pt.wikipedia.org/wiki/Thread_(ci%C3%AAncia_da_computa%C3%A7%C3%A3o)) + - Na prática: go func. + - Exemplo: código termina antes da go func executar. + - Ou seja, precisamos de uma maneira pra "sincronizar" isso. + - Ah, mas então... não. + - Qualé então? sync.WaitGroup: + - Um WaitGroup serve para esperar que uma coleção de goroutines termine sua execução. + - func Add: "Quantas goroutines?" + - func Done: "Deu!" + - func Wait: "Espera todo mundo terminar." + - Ah, mas então... sim! + - Só pra ver: runtime.NumCPU() & runtime.NumGoroutine() + - Go Playground: https://play.golang.org/p/8iiqLX4sWc + + - title: "Discussão: Condição de corrida" + text: | + - Agora vamos dar um mergulho na documentação: + - https://golang.org/doc/effective_go.html#concurrency + - https://pt.wikipedia.org/wiki/Multiplexador + - O que é yield? runtime.Gosched() + - Race condition: + *Função 1 var Função 2* + Lendo: 0 → 0 + Yield 0 → Lendo: 0 + var++: 1 Yield + Grava: 1 → 1 var++: 1 + 1 ← Grava: 1 + Lendo: 1 ← 1 + Yield 1 → Lendo: 1 + var++: 2 Yield + Grava: 2 → 2 var++: 2 + 2 ← Grava: 2 + - E é por isso que vamos ver mutex, atomic e, por fim, channels. + + - title: Condição de corrida + text: | + - Aqui vamos replicar a race condition mencionada no artigo anterior. + - time.Sleep(time.Second) vs. runtime.Gosched() + - go help → go help build → go run -race main.go + - Como resolver? Mutex. + - Código: https://github.com/ellenkorbes/aprendago/blob/master/c%C3%B3digo/18_concorrencia/05_race_condition/main.go + + - title: Mutex + text: | + - Agora vamos resolver a race condition do programa anterior utilizando mutex. + - Mutex é mutual exclusion, exclusão mútua. + - Utilizando mutex somente uma thread poderá utilizar a variável contador de cada vez, e as outras deve aguardar sua vez "na fila." + - Na prática: + - type Mutex + - func (m *Mutex) Lock() + - func (m *Mutex) Unlock() + - RWMutex + - Código: https://github.com/ellenkorbes/aprendago/blob/master/c%C3%B3digo/18_concorrencia/06_mutex/main.go + + - title: Atomic + text: | + - Agora vamos fazer a mesma coisa, mas com atomic ao invés de mutex. + - atomic.AddInt64 + - atomic.LoadInt64 + - Código: https://github.com/ellenkorbes/aprendago/blob/master/c%C3%B3digo/18_concorrencia/07_atomic/main.go diff --git a/internal/concorrencia/topics.go b/internal/concorrencia/topics.go new file mode 100644 index 0000000..b7b452d --- /dev/null +++ b/internal/concorrencia/topics.go @@ -0,0 +1,49 @@ +package concorrencia + +import ( + "fmt" + + "github.com/fabianoflorentino/aprendago/pkg/format" +) + +var rootDir = "internal/concorrencia" + +func Concorrencia() { + fmt.Printf("\n\n18 - Concorrência\n") + + executeSection("Concorrência vs Paralelismo") + executeSection("Goroutines & WaitGroups") + executeSection("Discussão: Condição de corrida") + executeSection("Condição de corrida") + executeSection("Mutex") + executeSection("Atomic") +} + +func MenuConcorrencia([]string) []format.MenuOptions { + return []format.MenuOptions{ + {Options: "--concorrencia-vs-paralelismo", ExecFunc: func() { executeSection("Concorrência vs Paralelismo") }}, + {Options: "--goroutines-waitgroups", ExecFunc: func() { executeSection("Goroutines & WaitGroups") }}, + {Options: "--discussao-condicao-de-corrida", ExecFunc: func() { executeSection("Discussão: Condição de corrida") }}, + {Options: "--condicao-de-corrida", ExecFunc: func() { executeSection("Condição de corrida") }}, + {Options: "--mutex", ExecFunc: func() { executeSection("Mutex") }}, + {Options: "--atomic", ExecFunc: func() { executeSection("Atomic") }}, + } +} + +func HelpMeConcorrencia() { + hlp := []format.HelpMe{ + {Flag: "--concorrencia-vs-paralelismo", Description: "Apresenta a diferença entre concorrência e paralelismo.", Width: 0}, + {Flag: "--goroutines-waitgroups", Description: "Apresenta o uso de goroutines e waitgroups.", Width: 0}, + {Flag: "--discussao-condicao-de-corrida", Description: "Apresenta uma discussão sobre condição de corrida.", Width: 0}, + {Flag: "--condicao-de-corrida", Description: "Apresenta o conceito de condição de corrida.", Width: 0}, + {Flag: "--mutex", Description: "Apresenta o uso de mutex.", Width: 0}, + {Flag: "--atomic", Description: "Apresenta o uso de atomic.", Width: 0}, + } + + fmt.Println("\nCapítulo 18: Concorrência") + format.PrintHelpMe(hlp) +} + +func executeSection(section string) { + format.FormatSection(rootDir, section) +} diff --git a/internal/menu/capitulo_options.go b/internal/menu/capitulo_options.go index 2fd11c7..0efd64e 100644 --- a/internal/menu/capitulo_options.go +++ b/internal/menu/capitulo_options.go @@ -5,6 +5,7 @@ import ( "github.com/fabianoflorentino/aprendago/internal/agrupamento_de_dados" "github.com/fabianoflorentino/aprendago/internal/aplicacoes" + "github.com/fabianoflorentino/aprendago/internal/concorrencia" "github.com/fabianoflorentino/aprendago/internal/exercicios_ninja_nivel_1" "github.com/fabianoflorentino/aprendago/internal/exercicios_ninja_nivel_2" "github.com/fabianoflorentino/aprendago/internal/exercicios_ninja_nivel_3" @@ -42,6 +43,7 @@ func MenuCapituloOptions([]string) []format.MenuOptions { {Options: "--cap-15 --topics", ExecFunc: func() { exercicios_ninja_nivel_7.HelpMeExerciciosNinjaNivel7() }}, {Options: "--cap-16 --topics", ExecFunc: func() { aplicacoes.HelpMeAplicacoes() }}, {Options: "--cap-17 --topics", ExecFunc: func() { exercicios_ninja_nivel_8.HelpMeExerciciosNinjaNivel8() }}, + {Options: "--cap-18 --topics", ExecFunc: func() { concorrencia.HelpMeConcorrencia() }}, } } @@ -64,6 +66,7 @@ func HelpMeCapituloOptions() { {Flag: "--cap-15 --topics", Description: "Exercícios Ninja: Nível 7", Width: 0}, {Flag: "--cap-16 --topics", Description: "Aplicações", Width: 0}, {Flag: "--cap-17 --topics", Description: "Exercícios Ninja: Nível 8", Width: 0}, + {Flag: "--cap-18 --topics", Description: "Concorrência", Width: 0}, } fmt.Println("Capítulos do Curso") diff --git a/internal/menu/helpme.go b/internal/menu/helpme.go index d3ae08f..a25ac2d 100644 --- a/internal/menu/helpme.go +++ b/internal/menu/helpme.go @@ -5,6 +5,7 @@ import ( "github.com/fabianoflorentino/aprendago/internal/agrupamento_de_dados" "github.com/fabianoflorentino/aprendago/internal/aplicacoes" + "github.com/fabianoflorentino/aprendago/internal/concorrencia" "github.com/fabianoflorentino/aprendago/internal/exercicios_ninja_nivel_1" "github.com/fabianoflorentino/aprendago/internal/exercicios_ninja_nivel_2" "github.com/fabianoflorentino/aprendago/internal/exercicios_ninja_nivel_3" @@ -58,4 +59,5 @@ func HelpMe() { exercicios_ninja_nivel_7.HelpMeExerciciosNinjaNivel7() aplicacoes.HelpMeAplicacoes() exercicios_ninja_nivel_8.HelpMeExerciciosNinjaNivel8() + concorrencia.HelpMeConcorrencia() } diff --git a/internal/menu/options.go b/internal/menu/options.go index 9abed94..412c2e0 100644 --- a/internal/menu/options.go +++ b/internal/menu/options.go @@ -30,6 +30,7 @@ import ( "github.com/fabianoflorentino/aprendago/internal" "github.com/fabianoflorentino/aprendago/internal/agrupamento_de_dados" "github.com/fabianoflorentino/aprendago/internal/aplicacoes" + "github.com/fabianoflorentino/aprendago/internal/concorrencia" "github.com/fabianoflorentino/aprendago/internal/exercicios_ninja_nivel_1" "github.com/fabianoflorentino/aprendago/internal/exercicios_ninja_nivel_2" "github.com/fabianoflorentino/aprendago/internal/exercicios_ninja_nivel_3" @@ -80,6 +81,7 @@ func Options(args []string) { exercicios_ninja_nivel_7.MenuExercicioNinjaNivel7(args), aplicacoes.MenuAplicacoes(args), exercicios_ninja_nivel_8.MenuExerciciosNinjaNivel8(args), + concorrencia.MenuConcorrencia(args), ) } diff --git a/internal/outline.go b/internal/outline.go index ffaf704..d5d4ea0 100644 --- a/internal/outline.go +++ b/internal/outline.go @@ -4,6 +4,7 @@ package internal import ( "github.com/fabianoflorentino/aprendago/internal/agrupamento_de_dados" "github.com/fabianoflorentino/aprendago/internal/aplicacoes" + "github.com/fabianoflorentino/aprendago/internal/concorrencia" "github.com/fabianoflorentino/aprendago/internal/exercicios_ninja_nivel_1" "github.com/fabianoflorentino/aprendago/internal/exercicios_ninja_nivel_2" "github.com/fabianoflorentino/aprendago/internal/exercicios_ninja_nivel_3" @@ -37,4 +38,5 @@ func Outline() { ponteiros.Ponteiros() exercicios_ninja_nivel_7.ExerciciosNinjaNivel7() aplicacoes.Aplicacoes() + concorrencia.Concorrencia() }