concorrencia101
  • Introdução
  • First things first
  • Agradecimentos
  • Parte I - Concorrência no sistema operacional
    • O que é o programa no sistema operacional
    • Escalonador preemptivo de tarefas
    • Uma nota sobre escalonamento cooperativo
    • Propriedades de um processo
    • Clone de processo (forking)
    • Clone leve de processo (thread)
    • Todo processo tem uma thread principal
    • Uma nota sobre paralelismo
    • Principais desafios em cenário de concorrência
      • Race condition
      • Sincronização com locks
      • Modelo de atores
    • E o I/O?
      • Latência de CPU vs Latência de I/O
      • Chamadas bloqueantes
      • Chamadas não-bloqueantes
      • Assincronismo e escalonamento cooperativo
    • Vamos colocar em prática...
  • PARTE II - Concorrência em diferentes linguagens
    • Definindo ambientes de execução
    • Concorrência em C
      • Forking de processos
      • Threads
      • Race condition e sincronização de threads com mutex
      • Desafios com o uso de threads
      • Thread Pool em C
      • Green threads
      • Modelo de Atores
      • Trabalhando com I/O
    • Concorrência em Ruby
      • Forking de processos
      • Threads
      • Race condition, YARV, GVL e paralelismo em Ruby
      • Modelo de Atores
      • Trabalhando com I/O
Powered by GitBook
On this page
  1. Parte I - Concorrência no sistema operacional
  2. E o I/O?

Assincronismo e escalonamento cooperativo

PreviousChamadas não-bloqueantesNextVamos colocar em prática...

Last updated 4 months ago

Escrever código assíncrono pode levar a alguns desafios na forma como escrevemos o código do programa. A natureza assíncrona nos obriga a definir estruturas que encapsulam a lógica a ser executada em outro contexto (callbacks), quando o I/O ficar pronto, o que pode levar a múltiplos callbacks chamando outros callbacks de forma aninhada, causando o que chamamos de callback hell.

Nenhuma linguagem está livre disto, pensando de forma abstrata

fn processData(callback):
  callToAction(callback() {
  }, anotherCallback {
  }, yetAnotherCallback {
  })...

E assim por diante...

Para mitigar este problema de indireção com assincronismo, podemos implementar técnicas funcionais como monads que lidam com tais efeitos colaterais. Por exemplo, estruturas como "async" e "await" presentes em algumas linguagens são uma forma de deixar o código mais "síncrono", encapsulando todo o efeito colateral do assincronismo em uma estrutura interna.

Desta forma, o código fica mais simples de manter, mitigando o problema com callback hell.

Outra forma de lidar com este problema é criando estruturas que permitem devolver o controle para o fluxo principal quando uma chamada de I/O assíncrono for identificada. Abstrações como corrotinas e fibers são vistas em diferentes linguagens para lidar com este problema.

Lembra do escalonamento cooperativo que vimos mais cedo no guia?

Então, com escalonamento cooperativo podemos fazer com que diferentes unidades de concorrência dentro do processo (coroutines ou fibers) possam cooperar com o uso de recursos, no caso I/O.

  • a corrotina delega controla para o loop com "yield", o que significa que ela ficará a espera de I/O

  • o loop não fica bloqueado e pode atender a outras corrotinas

  • quando o I/O fica pronto, o loop chama o "resume" na corrotina, devolvendo o controla e ela

Desta forma, I/O assíncrono e escalonamento cooperativo são grandes aliados para resolver o problema de assincronismo.


Está gostando deste meu trabalho? Buy me a coffee?

Ou copia e cola:

00020126850014BR.GOV.BCB.PIX013638ee4bde-574b-4197-b10f-68742087b00b0223Gratidão pelo cafezinho5204000053039865802BR5925Leandro Freitas Maringolo6009SAO PAULO62140510qrN6Ov1wRl63041A3C

Se até aqui gostou do que escrevi, considera me pagar um cafezinho maroto? Gratidão que define

❤️