Você está na página 1de 16

Universidade Federal do Tocantins.

 Em espera (processo esperando


Arraias, 04/06/2020. que algum evento ocorra);
Aluna: Gabrielle Azevedo.  Pronto (esperando para ser
Professor: Wosley Arruda. atribuído a um processador;
Disciplina: Sistemas Operacionais.  Concluído;
Esses nomes variam entre SOs.

Gerência de Processos Apenas um processo pode ser


executado em um processador por vez,
embora muitos processos possam estar em
espera ou prontos.
Processos Bloco de Controle de Processo
É um programa em execução.
Um sistema é composto por um Cada processo é representado no SO
conjunto de processos do Sistema por um bloco de controle de processo (PCB)
Operacional executando códigos tanto para – também chamado de bloco de controle de
o sistema quanto para os usuários. tarefa.
Processos podem ser executados de O PCB contém muitas informações
forma concorrente com a CPU (ou CPUs) associadas a um processo específico,
multiplexada alternando entre eles, incluindo:
possibilitando que o SO torne o computador  Estado do processo;
mais produtivo.  Contador do programa (indica a
Antigamente, usava-se os termos jobs, próxima instrução a ser executada)
mas processo os substituiu.  Registradores da CPU (devem ter
suas informações salvas, junto com
O processo o contador do programa, para ser
retomado, mesmo que haja uma
O processo é mais que o código do interrupção.
programa, incluindo a atividade corrente,  Informações de scheduling
representada pelo contador do programa e (incluem a prioridade de um
o conteúdo dos registradores do processador, processo, ponteiros para filas de
e incluindo ainda a pilha do processo, que scheduling e outros parâmetros de
contém os dados temporários, e uma seção scheduling)
de dados, que contém variáveis globais.  Informações do gerenciamento de
Pode incluir ainda um heap (memória memória
dinamicamente alocada durante o tempo  Informações de status de I/O
de execução do processo). (incluem lista de dispositivos de I/O
O processo é uma entidade ativa, com alocados ao processo, lista de
um contador de programa especificando arquivos abertos etc.)
qual será a próxima instrução e o conjunto de Um PCB é simplesmente o repositório
recursos associados. de todas as informações que possam variar
Mesmo que dois processos estejam entre os processos.
associados ao mesmo programa, ainda são
considerados sequências de execução Threads
separadas.
É comum que um processo gere muitos A maioria dos SOs atualmente permite
outros processos ao ser executado. que um processo tenha múltiplos threads de
execução, desempenhando mais de uma
Estado do Processo atividade por vez.
Em sistemas que suportam threads, o
Sempre que um processo é executado, PCB é expandido para incluir as informações
seu estado muda. Esse estado é definido, em de cada thread.
parte, pela atividade corrente do processo,
que pode ser:
 Novo
 Em execução
Schedulers
Scheduling Processos
Um processo passa por várias filas de
O objetivo da multiprogramação é Scheduling durante sua vida e o SO deve
que sempre haja processos em execução selecionar processos nessa fila de alguma
para maximizar o uso da CPU. Já o objetivo forma. O processo de seleção é feito pelo
do compartilhamento de tempo é alternara a schedule apropriado.
CPU entre os processos tantas vezes, que os Muitas vezes, em um sistema batch
usuários possam interagir com cada mais processos são submetidos do que é
programa enquanto ele está sendo possível executar, por isso, eles são
executado. Para alcançar esses objetivos, o armazenados em uma memória de massa,
scheduler de processos seleciona um aonde fica até a execução posteriormente.
processo disponível (ou processos disponíveis) Scheduler de longo prazo (ou
para execução na CPU. scheduler de jobs), selecionas processos
nesse pool e o carrega na memória para
Filas de Scheduling execução.
O scheduler de curto prazo (ou
Os processos que entram no sistema scheduler da CPU seleciona os processo
ficam em uma fila de jobs, que contém todos prontos e aloca a CPU para um deles.
os processos do sistema. A diferença entre esses dois scheduler
Os processo da memória principal que está na frequência de execução: o de curto
estão prontos para execução, ficam em uma prazo é executado ao menos uma vez a
fila de prontos. cada 100 milissegundos, enquanto o de longo
O cabeçalho de uma fila de prontos prazo é executado com muito menos
contém ponteiros para o 1º e o último PCBs da frequência.
lista. Cada PCB inclui um ponteiro para o O de longo prazo controla ainda o
próximo PCB da lista. grau de multiprogramação. Ele pode ser
O pai de um processo é o processo que invocado apenas quando um processo deixa
o criou e seus filhos, são quaisquer processos o sistema.
que ele tenha criado. Seus irmãos são A maioria dos processos são ou
processos que tenham o mesmo pai. limitados por I/O (gasta mais tempo fazendo
Quando a CPU é alocada para um I/O do que executando computação) ou
processo, ele é executado por um tempo até limitados por CPU (Executa mais computação
ser interrompido ou colocado em espera pela do que solicita I/O). Um sistema terá melhor
ocorrência de algum evento específico. desempenho ao combinar os dois.
A lista de processos em espera por um Em alguns sistemas, o scheduler de
dispositivo de I/O é chamada de fila do longo prazo pode ser ausente ou mínimo.
dispositivo e cada dispositivo tem sua fila Alguns sistemas, incluem um scheduler
própria. intermediário – às vezes pode ser vantajoso
Primeiro, um processo é colocado na remover um processo da memória, reduzindo
fila de prontos e fica lá até ser selecionado o grau de multiprogramação e, depois, este
para ser executado (despachado). Quando processo pode ser reintroduzido na memória
a CPU é alocada ao processo e este entra em (esse processo é chamado de swapping).
execução, vários eventos podem ocorrer: O swapping pode retirar sobrecargas
 O processo faz uma solicitação de ou melhorar o mix de processos.
I/O, sendo, então, inserido em uma
fila de I/O. Mudança de Contexto
 O processo cria um processo-filho e
espera que ele termine. Uma mudança de contexto ocorre
 O processo é removido à força da quando um processo é interrompido e o seu
CPU por causa de uma interrupção estado precisa ser salvo (salvamento de
e deve ser devolvido à fila de estado) – salvo no PCB pelo kernel – para
prontos. depois ser retomado (restauração do
Um processo fica nesse ciclo até ser estado).
finalizado – quando é removido de todas as O tempo gasto na mudança de
filas. contexto é puro overhead, já que o sistema
não executa trabalho útil durante a troca de Quando um processo cria um novo
processos. processo, há duas possibilidade de
execução:
Multitarefa em Sistemas Móveis  O pai continua a ser executado
junto com seus filhos.
IOS 4 dá suporte à multitarefa  O pai espera até que alguns de
(processo é executado em background se ser seus filhos ou todos eles sejam
suspenso), ficando disponível apenas para encerrados.
um número limitado de aplicações que: Duas possibilidades de
 Executam uma única tarefa de endereçamento para o novo processo:
tamanho finito.  O processo-filho é uma duplicata
 Recebem notificações sobre a do processo-pai.
ocorrência de um evento.  O processo-filho tem um novo
 Têm tarefas de background de programa carregado nele.
longa execução.
Android não tem essas restrições de Encerramento de Processos
tipos de aplicações. Se uma aplicação
precisa ser processada em background, ela Um processo se encerra quando a
usa um serviço (componente separado da execução do seu último comando é
aplicação que é executado em nome do finalizado e ele solicita a própria exclusão ao
processo de background). SO.
Um processo pode causar o
encerramento de outro através de uma
Operações sobre Processos chamada de sistema apropriada –
usualmente, apenas o pai pode fazer isso.
Como os processos são muito O pai precisa saber as identidades de
dinâmicos, na maioria dos sistemas, os seus filhos para encerrá-los.
sistemas devem fornecer mecanismo para O pai pode encerrar o seu filho por
criação e encerramento de processos. várias razões:
 O filho excedeu o uso de algum dos
Criação de Processos recursos que recebeu.
 A tarefa atribuída ao filho não é
Durante sua execução, um processo mais necessária.
pode criar vários processos novos.  O pai está sendo encerrado e o SO
A maioria dos SOs identifica os só pode fazer isso após encerrar
processos de acordo com um identificador seus filhos.
de processo (PID) exclusivo que, Alguns sistemas não permitem que seu
normalmente, é um número inteiro. O PID filho exista se o seu pai for encerrado. O
pode ser usado ainda como um índice de encerramento dos filhos para chegar ao do
acesso a vários atributos de um processo pai é chamado de encerramento em
dentro do kernel. cascata e geralmente é iniciado pelo SO.
Quando um processo cria um Um processo que foi encerrado, mas
processo-filho, este precisa de recursos, para seu pai ainda não chamou o wait() – que
executar a sua tarefa, que podem ser obtidos permite que o pai saiba o status do filho – é
através do SO ou pode ficar restrito a um chamado de processo zumbi.
subconjunto dos recursos do processo-pai Se um pai não chamasse o wait() e
(neste caso, o processo-filho é impedido de fosse encerrado, deixando seus filhos, estes se
sobrecarregar o sistema). tornariam órfãos.
O pai pode dividir seus recursos entre os
seus filhos ou pode compartilhar alguns
recursos (como memória e arquivos) com Comunicação Interprocessos
vários deles.
Além de fornecer diversos recursos Os processos executados
físicos e lógicos, o processo-pai pode passar, concorrentemente podem ser
na inicialização, dados (entradas) ao independentes (que não compartilham
processo-filho.
dados entre si) ou cooperativos (quando ocorre por meio de mensagens trocadas
pode ser afetado ou afetar outros processos). entre os sistemas cooperativos).
Os dois modelos são muito comuns e
Arquitetura Multiprocessos – Navegador muitos SOs implementam ambos.
Chrome A transmissão de mensagens é útil para
troca de pequenas quantidades de dados e
As vezes um navegador pode cair. Isso mais fácil de implementar em um sistema
não é um problema quando ele exibe distribuído. Melhor também para sistemas
problemas de apenas um website, mas, a com vários núcleos de processamento.
maioria dos navegadores atuais fornecem A memória compartilhada, no entanto,
navegação em guias, o que torna sua queda pode ser mais rápida.
um problema, já que todo o processo,
inclusive as outras guias, também cairá. Sistemas de Memória Compartilhada
O Chrome resolve esse problema
usando uma arquitetura Multiprocessos. Ele Normalmente, a região de memória
identifica três tipos de processos: compartilhada reside no espaço de
 Navegador: gerencia a interface endereçamento do processo que cria o
do usuário e o I/O de disco e de segmento de memória compartilhada.
rede. Criado apenas uma vez, Processos que queiram usar esse segmento,
quando o Chrome é iniciado. devem anexá-lo ao seu espaço de
 Renderizadores: Contêm a lógica endereçamento, já que o SO tenta impedir
para renderização de páginas que um processo acesse a memória do outro
web. É criado para cada website processo, por isso, a memória compartilhada
aberto em uma guia. requer que dois ou mais processos
 Plugin: Criado para cada tipo de concordem em eliminar essa restrição.
plugin (como Flash) em uso. A forma dos dados e a locação são
Vantagens da abordagem determinadas pelos próprios processos, pois
multiprocesso: eles não ficam sob controle do SO. Eles ainda
 Websites são executados são responsáveis por garantir que eles não
isoladamente e, se um cai, ele não estão fazendo gravações na mesma locação
afeta os outros. simultaneamente.
 processos renderizadores são Um paradigma comum dos processos
executados em uma sendbox, logo, cooperativos é o problema do produtor
o acesso ao I/O de disco e rede é consumidor. Um processo produtor é aquele
limitado, minimizando efeitos que produz informações para serem
invasões na segurança. consumidas por um processo consumidor.
 Aumento da velocidade de Para permitir que os processos
computação (apenas para produtores e consumidores sejam executados
computadores com vários núcleos concorrentemente, o produtor e o
de processamento). consumidor devem estar sincronizados para
 Modularidade, ao dividir suas que o consumidor não tente consumir um
funções em processos ou threads item que ainda não foi produzido.
separados. Para isso, dois tipo de buffer podem ser
 Conveniência, já que um usuário usados: o ilimitado (sem tamanho prático em
pode trabalhar em muitas tarefas seu tamanho), em que o consumidor pode ter
ao mesmo tempo. que esperar por novos itens, mas o produtor
sempre pode produzir novos itens, e o buffer
Processos cooperativos demandam limitado (com tamanho fixo) em que o
um mecanismo para comunicação entre consumidor deve esperar se o buffer estiver
processos (IPC), para troca de dados e vazio, e o produtor deve esperar se ele estiver
informações. Há dois modelos básicos de cheio.
IPCs: memória compartilhada (uma região da
memória é compartilhada, permitindo que Sistemas de Transmissão de Mensagens
eles troquem informações lendo e gravando
dados na região compartilhada) e Nele, as mensagens enviados por um
transmissão de mensagens (a comunicação processo podem ser de tamanho fixo ou
variável.
Os métodos para implementar Recebimento sem bloqueio: O
logicamente um link e as operações send()/ receptor recupera uma mensagem válida ou
receive(): nula.
 Comunicação direta ou indireta
 Comunicação síncrona ou Independentemente de a
assíncrona comunicação ser direta ou indireta, as
 Armazenamento em buffer mensagens trocados por processos em
automático ou explícito. comunicação residem em uma fila
Na comunicação direta, cada temporária. Essas filas podem ser
processo que se comunicar deve nomear implementadas de três maneiras:
explicitamente o receptor ou o emissor da  Capacidade zero (ou sistemas de
comunicação. armazenamento sem
Há simetria no endereçamento armazenamento em buffer): Fila
quando tanto o processo emissor quanto tem tamanho máximo de zero,
receptor devem nomear um ao outro para se logo, o link não pode ter
comunicar. Uma variante emprega a mensagens em espera.
assimetria no endereçamento, em que o  Capacidade limitada: fila de
receptor não precisa nomear o emissor. tamanho finito em que no máximo
A desvantagem do simétrico e do n mensagens podem residir nela.
assimétrico é a modularidade limitada das  Capacidade ilimitada: número de
definições dos processos resultantes. mensagens potencialmente infinito,
Na comunicação indireta, as podendo conter várias mensagens
mensagens são enviadas para e em espera.
recebidas de caixas postais, ou portas. Tanto o de capacidade limitada como
Abstratamente, uma caixa postal é um ilimitada são conhecidas como sistemas com
objeto no qual a mensagem pode ser inserida armazenamento em buffer automático.
por processo e do qual mensagens podem ser
removidas. Cada caixa postal tem uma
identificação exclusiva. Exemplos de Sistemas IPC
Uma caixa postal pode ser
propriedade de um processo ou do SO. Se Memória compartilhada POSIX:
ela é propriedade do processo, faz-se a organiza a memória compartilhada com o
distinção entre o proprietário (que só pode uso de arquivos mapeados para a memória,
receber mensagem por essa caixa postal) e o que associam a região da memoria
usuário (que só envia mensagem para a compartilhada a um arquivo.
caixa postal). Mach – Com transmissão de
Uma caixa postal que é propriedade mensagens: A maior parte da comunicação
do SO tem existência própria e não está (incluindo todas as informações entre tarefas)
associada a nenhum processo específico. é executada por mensagens, que são
Logo, é o SO que deve: enviadas e recebidas em caixas postais
 Criar uma nova caixa postal (chamadas portas no Mach). Ele garante que
 Enviar e receber mensagens pela várias mensagens do mesmo emissor sejam
caixa postal enfileiradas na ordem FIFO (primeiro a entrar,
 Excluir uma caixa postal. primeiro a sair), mas não garante ordem
A transmissão de mensagens pode ser absoluta.
com bloqueio (síncrona) ou sem bloqueio As mensagens propriamente ditas são
(assíncrona). compostas por um cabeçalho de tamanho
Envio com bloqueio: o processo emissor fixo, seguido por uma parte de dados de
é bloqueado até que a mensagem seja tamanho variável. O cabeçalho indica o
recebida pelo receptor ou pela caixa postal. tamanho da mensagem e inclui dois nomes
Envio sem bloqueio: o emissor envia a de caixa postal em que, um especifica a
mensagem e retoma a operação. caixa posta para a qual a mensagem será
Recebimento com bloqueio: O enviada. Normalmente, o thread emissor
receptor é bloqueado até que a mensagem espera uma resposta, passando assim o nome
fique disponível. da caixa postal do emissor à tarefa receptora,
que a usará como endereço de retorno.
A parte variável da mensagem é uma conexão a essa porta. O servidor cria um
lista de dados tipificados. Cada entrada da canal e retorna um manipulador para o
lista tem um tipo, valor e tamanho. cliente.
As operações de envio e recebimento O canal tem um par de portas de
são flexíveis. comunicações privadas: um para mensagens
Quando a caixa postal está cheia, o cliente-servidor, outro para mensagens
thread emissor tem quatro opções: servidor-cliente. Os canais de comunicação
 Esperar até haver espaço na caixa dão suporte ainda a um mecanismo de
postal. retorno de chamada que permite que o
 Esperar no máximo n milissegundos. cliente e o servidor aceitem solicitações
 Não esperar e retornar quando estariam esperando uma resposta.
imediatamente. Quando um canal ALPC é criado, há
 Armazenar a mensagem, três técnicas possíveis de mensagens a ser
temporiamente, em cache. selecionadas:
Quando a mensagem puder ser  Para mensagens pequenas (até 256
inserida na caixa postal, outra mensagem bytes) a fila de mensagens da porta
será retornada ao emissor. e usada como repositório
A operação de recebimento deve ser intermediário, e as mensagens são
especificada a caixa postal ou o conjunto de copiadas de um processo para o
caixas postais (coleção de caixas postais que outro.
podem ser agrupadas e tratadas como uma  Mensagens maiores devem ser
única caixa postal) a partir das quais uma passadas por um objeto seção
mensagem deve ser recebida. (região de memória compartilhada
Os threads de uma tarefa podem associada ao canal.
receber mensagens somente de uma caixa  Quando o volume é grande
postal ou conjunto de caixas postais para as demais, existe uma API disponível
quais a tarefa tenha acesso de recebimento. que permite que processos de
Se nenhum mensagem está em espera servidor leiam e gravem
para ser recebida, o thread pode esperar um diretamente no espaço de
tempo limitado ou não esperar. endereçamento de um cliente.
O sistema Mach foi projetado para
sistemas distribuídos, mas se mostrou útil
também para sistemas com menos núcleos Comunicação em Sistemas
de processamento.
O principal problema dos sistemas de ClienteServidor
mensagens é o fraco desempenho, causado
pela cópia dupla da mensagem. A memória compartilhada e
Windows: Emprega a modularidade transmissão de mensagens também podem
para aumentar a funcionalidade e reduzir o ser usadas para comunicação em sistemas
tempo necessário à implementação de clienteservidor, mas há ainda outras três
novos recursos. estratégias: sockets, chamadas de
O sistema de mensagens do Windows procedimento remotas (RPCs) e pipes.
é denominado chamada de procedimento
local avançado (ALPC) e é usado na Sockets
comunicação entre dois processo na mesma
máquina. Uma extremidade de comunicação.
Também usa objetos para estabelecer Um par de processos que estão se
e manter uma conexão entre dois processos. comunicando através de uma rede emprega
Usa dois tipos de portas: portas de um par de sockets – um para cada processo.
conexão e portas de comunicação. Um socket é identificado por um
Os processo de servidor publicam endereço IP concatenado com um número
objetos portas de conexão que podem ser de porta e geralmente usam uma arquitetura
vistos por todos os processos. clienteservidor, em que o servidor espera
Quando um cliente requer os serviços solicitações recebidas de clientes ouvindo
de algum subsistema, ele abre um uma porta específica.
manipulador para o objeto porta de conexão
do servidor e envia uma solicitação de
Uma vez que a solicitação é recebida, stub localiza a porta no servidor e organiza os
o servidor aceita uma conexão vinda do parâmetros.
socket do cliente para completá-la. O stub envia, então, uma mensagem
Servidores que implementam serviços par ao servidor usando transmissão de
específicos (FTP, HTTP etc.) ouvem em portas mensagens. Um stub semelhante no lado do
bem conhecidas (abaixo de 1024). servidor recebe essa mensagem e invoca o
Quando um processo cliente inicia a procedimento no servidor. Se necessário,
solicitação de uma conexão, uma porta é valores de retorno são devolvidos ao cliente
atribuída a ele pelo computador hospedeiro. com o uso da mesma técnica.
Os pacotes que viajarem entre os Uma questão a ser tratada é a
hospedeiros serão liberados para o processo diferença de representação de dados nas
apropriado com base no número da porta de máquinas do cliente e do servidor. Para
destino. resolver isso, muitos RPCs definem uma
Todas as conexões devem ser representação de dados independente da
exclusivas. máquina, sendo conhecida como
A linguagem Java tem três tipos de representação de dados externa (XDR). No
sockets diferentes: sockets orientados à lado do cliente, pega os dados e faz a
conexão (TCP), sockets sem conexão (UDP) e conversão XDR e no lado do servidor pega o
socket multicast (que permite que os dados XDR e converte para a máquina do servidor.
sejam enviados a vários receptores). As PRCs podem falhar ou ser
Mesmo que a comunicação com duplicadas e executas mais de uma vez por
sockets seja comum e eficiente, é erros de rede. Para resolver isso, o SO pode
considerada de baixo nível entre os processo assegurar que as mensagens sejam
distribuídos. Um dos motivos é que eles manipuladas exatamente uma vez, no lugar
permitem que somente um fluxo não de no máximo uma vez.
estruturado de bytes seja trocado entre os O esquema RPC requer uma
threads que estão se comunicando. associação entre a porta do cliente e do
servidor. Para os clientes saberem o número
Chamadas de Procedimento Remotas (RPC) da porta do servidor, há duas abordagens
comuns. Na primeira, as informações da
Foi projetada como uma forma de associação são predeterminadas, com
abstrair o mecanismo de chamada de endereços de porta fixos. Na segunda, a
procedimento para uso entre sistemas com associação é obtida de forma dinâmica por
comunicação de rede. um mecanismo de ponto de encontro
As mensagens trocadas na RPC são (também chamado de matchmaker).
bem estruturadas, não sendo apenas O RPX é útil em sistemas distribuídos.
pacotes de dados. Cada mensagem é
endereçada a um daemon RPC, escutando Pipes
em uma porta do sistema remoto, e contém
um identificador especificando a função a Um pipe atua como canal que permite
ser executada e os parâmetros a serem que dois processos se comuniquem.
passados para a função. Essa função é Fornecem uma das maneiras mais simples de
executada, como solicitado, e qualquer comunicação de processos, embora haja
saída é retornada ao solicitante em uma limitações.
mensagem separada. Dois tipos comuns de pipes:
Uma porta é um número incluído no  Pipes comuns: permitem que dois
início de um pacote de mensagem. Quando processos se comuniquem na
um processo remoto precisa de um serviço, forma produtor-consumidor: o
ele endereça a mensagem à porta produtor grava em uma
apropriada. extremidade do pipe (a
O RPC oculta os detalhes que extremidade de gravação) e o
permitem ocorrência da comunicação, consumidor lê da outra
fornecendo um stub no lado do cliente. extremidade (extremidade de
Quando o cliente invoca um procedimento leitura). São unidirecionais
remoto, o sistema RPC chama o stub (comunicação apenas em uma
apropriado, passando os parâmetros direção). Se for necessário
fornecidos ao procedimento remoto. Esse comunicação bidirecional, dois
pipes devem ser usados, enviando  Economia.
informações em direções opostas.  Escalabilidade (principalmente em
Ele não pode ser acessado de fora arquiteturas com
do processo que o criou. multiprocessadores).
Geralmente o pai cria um pipe para
se comunicar com o filho.
 Pipes nomeados: A comunicação Programação Multicore
pode ser bidirecional, e nenhum
relacionamento pai-filho é Quando há múltiplos chips de
necessário. Uma vez que um pipe é computação no mesmo chip, cada núcleo é
estabelecido, vários processos visto como um processador separado para o
podem usá-lo. SO. A isso, dá-se do nome de multicore ou
multiprocessadores.

Threads – Visão Geral threads


O uso da programação com múltiplos
melhora o eficiência dos
multiprocessadores e aumenta a
Uma thread é a unidade básica de concorrência.
utilização da CPU, composto por: um ID de Os threads podem ser executados em
thread, contador de programa, conjunto de paralelo, já que cada núcleo pode executar
registradores e uma pilha. um thread.
Um thread compartilha sua seção de Diferença entre paralelismo e
código, a seção de dados e outros recursos concorrência: O sistema é paralelo quando
so sistema com outros threads pertencentes pode executar mais de uma tarefa ao mesmo
ao mesmo processo. tempo. Já a concorrência, é quando um
Um processo tradicional tem apenas sistema consegue ir trocando entre várias
um thread de controle, mas se ele tem mais tarefas de forma que elas progridam.
threads, ele pode executar mais de uma
tarefa ao mesmo tempo. Desafios da Programação

Motivação Cinco áreas apresentam desafios para


a programação de sistemas multicore:
A maioria das aplicações de software  Identificação de tarefas que
atuais usam mais de um thread (multithreads). possam ser divididas em tarefas
Uma aplicação é geralmente implementada separas e concorrentes.
como um processo separado com diversos  Equilíbrio, por parte dos
threads de controle. programadores, para assegurar
O método de criação de processos era que as tarefas desenvolvam
comum antes dos threads, mas foram esforço igual ou de mesmo valor.
substituídos, pois a criação de processos é  Divisão de dados para execução
mais demorada e usa mais recursos. em núcleos separados.
Os threads têm grande importância  Dependência de dados. Os dados
em sistemas com chamadas de acessados pelas tarefas devem ser
procedimentos remotas (RPCs). examinados para determinar
Quando o servidor recebe uma dependências entre duas ou mais
mensagem, ele a atende usando um thread tarefas.
separado, permitindo que ele atenda a várias  Teste e depuração. Quando um
solicitações ao mesmo tempo. programa está sendo executado
em paralelo em múltiplos núcleos,
Benefícios podem existir caminhos de
execução diferentes.
 Capacidade de resposta
aumentada para o usuário. Tipos de Paralelismo
 Compartilhamento de recursos
(através de técnicas como O paralelismo de dados foca na
memória compartilhada ou distribuição de subconjuntos dos mesmo
transmissão de mensagens). dados, por múltiplos núcleos de computação,
e na execução da mesma operação em kernel pode incluir no schedule apenas um
cada núcleo. thread por vez.
O paralelismo de tarefas foca na Uma de suas variações multiplexa
distribuição de tarefas (threads) em vários muitos threads de usuário para um número
núcleos, e diferentes threads podem estar menor ou igual de threads de kernel, mas
operando sobre os mesmo dados. também permite que um thread de nível de
O paralelismo de dados foca na usuário seja limitado a um thread de kernel.
distribuição de dados entre os núcleos. Essa variação é, às vezes referenciada como
modelo de dois níveis.

Modelos de Geração de
Bibliotecas de threads
Multithreads
Uma biblioteca de threads fornece ao
O suporte aos threads pode ser: programador uma API para criação e
 no nível do usuário (threads de gerenciamento de threads. Há duas maneiras
usuário): suportados acima do principais de implementá-las: Primeiro,
kernel e gerenciados sem o suporte fornecer uma biblioteca inteiramente no
do kernel. espaço do usuário sem suporte do kernel, em
 ou pelo kernel (threads de kernel): que todo o código e estrutura de dados dela
Suportados e gerenciados estão no espaço do usuário. A segunda forma
diretamente pelo SO. é a implementação de um biblioteca no nível
Deve existir um relacionamento entre do kernel com suporte direto do SO.
os dois tipos acima. Três bibliotecas de threads principais
são usadas atualmente: a Pthreads do POSIX,
Modelos MuitosParaUm a do Windows e a de Java.
Duas estratégias gerais para a criação
Mapeia muitos threads de nível de de múltiplos threads é a síncrona e assíncrona.
usuário para um thread de kernel. Na criação de threads assíncrona,
O gerenciamento dos threads é feito cada thread é executado de forma
no espaço do usuário, sendo eficiente. independente e o pai não precisa saber
Todo o processo pode ser bloqueado quando o filho terminou. Geralmente há
se um thread fizer uma chamada de sistema pouco compartilhamento de dados entre
bloqueadora. eles.
Na criação de threads síncrona, o pai
Modelo UmParaUm precisa esperar que todos os filhos terminem
para ele voltar a ser executado (estratégia
Mapeia cada thread de usuário para conhecida como forkjoin).
um thread de kernel.
Fornece mais concorrência que o
muitos-para-um.
Permite que múltiplos threads sejam Threading Implícito
executados em paralelo em
multiprocessadores. Com o crescimento do processamento
Desvantagem: a criação de um thread multicore, aplicações contendo muitas
de usuário requer a criação de um thread de threads estão surgindo, mas projetar essas
kernel. aplicações não é algo simples.
Uma forma de tornar isso mais simples é
Modelos MuitosParaMuitos transferindo a criação e o gerenciamento de
threads dos desenvolvedores para os
Multiplexa muitos threads de usuário compiladores e bibliotecas de tempo de
para um número menor ou igual de threads execução. Essa estratégia é chama de
de kernel. Threading Implícito. Há três alternativas para
Permite que o desenvolvedor crie os o projeto de programas multithreads que
quantos threads o usuário quiser, mas não tiram proveito de processadores multicore por
resulta em uma concorrência real, pois o meio do threading implícito.
Pool de Threads Se o thread em um programa chamar
fork ( ), o novo processo duplicará todos os
Criação de múltiplos threads na threads, ou o novo processo será um púnico
inicialização do processo, bem como a thread. Alguns sistemas UNIX têm duas versões
inserção dos threads em um pool, onde eles de fork ( ), uma para cada uma dessas
ficarão esperando para entrar em ação. opções.
Quando o serviço terminar a ação, ele Se um thread chamar exec ( ), o
retorna para o pool. Se o pool não tem thread programa especificado como parâmetro
disponível, ele espera. substituirá o processo inteiro – inclusive nos
Isso resolve o problema do gasto do UNIX, um sinal é usado para mostrar que
tempo de criação para threads, a falta ade determinado evento ocorreu. O sinal pode ser
aproveitamento dele depois e evita que os síncrono ou assíncrono e seguem o mesmo
recursos do sistema sejam exauridos. padrão:
 Um sinal é gerado pela ocorrência
OpenMP de um evento específico.
 O sinal é liberado para um
Conjunto de diretivas de computação processo.
assim como uma API para programas escritos  Uma vez liberado, ele deve ser
em C, C++ ou FORTRAN. manipulado.
Ele identifica regiões paralelas como Dois manipuladores possíveis de sinais:
blocos de códigos que podem ser  Um manipulado default.
executados em paralelo, permite que os  Um manipulador definido pelo
desenvolvedores escolham entre vários níveis usuário.
de paralelismo e permite que os Para onde o sinal deve ser liberado:
desenvolvedores identifiquem se os dados  Para o thread ao qual ele é
são compartilhados entre threads ou se são aplicável.
privados de um thread.  Para cada thread do processo
 Para certos threads do processo
Grand Central Dispatch  Designar um thread específico para
receber todos os sinais do processo.
Também chamado de GCD é uma
tecnologia para SOs Mac OS X e IOS da Cancelamento de Threads
Apple. Ele é uma combinação de extensões
para a linguagem C, uma API e uma Envolve o encerramento de um thread
biblioteca de tempo de execução que antes de ele ser concluído.
permite aos desenvolvedores de aplicações Um thread a ser cancelado é
identificarem seções de códigos a serem chamado de thread-alvo.
executados em paralelo. O cancelamento pode ocorrer em dois
cenários:
Outras Abordagens  Cancelamento assíncrono: thread
encerrado imediatamente.
Incluem bibliotecas paralelas e Geralmente o SO reclama os
concorrentes, como Threading Building Blocks recursos do thread cancelado, mas
(TBB) da Intel e vários produtos da Microsoft. não todos.
 Cancelamento adiado. É o
cancelamento default
Questões Relacionadas com a
Armazenamento Local do Thread
Criação de Threads
Algumas vezes, cada thread pode
Chamadas de Sistema Fork() e Exec() precisar de sua própria cópia de certos dados
(esses dados são chamados de
A chamada de sistema fork ( ) é usada armazenamento local do thread ou TLS)
para criar um processo duplicado separado. As variáveis locais são visíveis apenas
A semântica dessas chamadas muda durante uma única invocação de função,
em um programa com múltiplos threads. enquanto os dados TLS são visíveis ao longo
das invocações de funções. A diferença é
que os dados TLS são únicos para cada executado em modalidade de
thread. kernel.
 Área de armazenamento privada
Ativação do Scheduler usada para várias bibliotecas de
tempo de execução e bibliotecas
Muitos sistemas que implementam o de links dinâmicos (DLLs).
modelo muito-para-muitos ou de dois níveis O conjunto de registradores, as pilhas e
inserem uma estrutura de dados as áreas de armazenamento são chamadas
(normalmente conhecida como peso leve ou de contextos do thread.
LWP) intermediária entre os threads do usuário Principais estruturas de dados de uma
e do kernel. thread:
Para a biblioteca de threads do  ETHREAD – bloco de thread
usuário, o LWP aparece como um exclusivo.
processador virtual em que a aplicação pode  KTHREAD – bloco de thread do
incluir no schedule um thread de usuário para kernel.
execução. Cada LWP é anexado a um  TEB – bloco de ambiente do thread.
thread do kernel que o SO inclui no schedule
para execução em processadores físicos. Se Threads no Linux
um thread do kernel for bloqueado o LWP
também será. Fornece a chamada fork ( ) com a
Uma aplicação pode requerer funcionalidade tradicional de duplicar um
quantos LWPs quiser para ser executada processo. Fornece também a chamada
eficientemente. clone ( ) para criar threads. No entanto, o
A ativação do schedule é usada para Linux não diferencia processos e threads. Ele
a comunicação entre a biblioteca de threads usa o termo tarefa ao se referir a um fluxo de
de usuário e o kernel. Nele, o kernel fornece controle dentro de um programa.
uma aplicação um conjunto de
processadores virtuais (LWPs), e a aplicação
pode incluir no schedule threads de usuário Antecedentes
para um processador virtual disponível. Além
disso, o kernel deve informar a aplicação Uma situação em que vários processos
sobre certo eventos (procedimento acessam e manipulam os mesmos dados e o
chamado de upcall). As upcalls são concorrentemente e o resultado depende da
manipuladas pela biblioteca de threads com ordem em que processo ocorre é chamada
um manipulador de upcalls que deve ser de uma condição de corrida. Para saber a
executado em um processador virtual. ordem, é necessária alguma forma de
sincronização.

Exemplos de SOs A Seção Crítica


Threads no Windows Cada código tem sua seção crítica em
que o processo pode estar alterando
Uma aplicação no Windows é variáveis comuns, atualizando uma tabela,
executada como um processo separado, e gravando um arquivo etc.
cada processo pode conter um ou mais Quando um processo está executando
threads. Usa ainda o mapeamento um-para- sua seção crítica, nenhum outro processo
um. deve ter autorização para fazer o mesmo.
Os componentes gerais de um thread: Cada processo deve solicitar para
 ID de identificação entrar me sua própria seção crítica. A seção
 Conjunto de registradores que de código que implementa essa solicitação é
representam o status do a seção de entrada. A seção crítica pode ser
processador seguida por uma seção de saída. O código
 Uma pilha de usuário, quando restante é a seção remanescente.
usado thread de usuário e uma Uma solução para esse problema deve
pilha de kernel quando está sendo conter:
 Exclusão mútua seção crítica, se outro tentar entrar, pode
 Progresso ficar esperando em um loop infinito, sendo
 Espera limitada. claramente um problema em um sistema de
programação real. A espera da ação
Para isso, dois métodos são usados: desperdiça ciclos da CPU que alguns
 Kernel com preempção: permite processos poderiam usar produtivamente.
que um processo seja interceptado Vantagem: nenhuma mudança de
quando está sendo executado em contexto é requerida quando um processo
modalidade de kernel. tem de esperar em um lock, e uma mudança
Podem apresentar melhor de contexto pode levar um tempo
capacidade de resposta. Mais considerável.
apropriado para programação em Assim, os spinlocks são úteis quando o
tempo real. uso de locks ocorrerá por períodos curtos.
 Kernel sem preempção: não
permite que um processo sendo
executado seja interceptado em Semáforos
modalidade de kernel.
Semelhante ao lock mutex, mas mais
robusto. Quando um processo modifica o
Hardware de Sincronização valor do semáforo, nenhum outro processo
pode modificar o valor desse mesmo
Soluções para o problema da seção semáforo simultaneamente.
crítica usando técnicas que variam do
hardware à APIs baseadas em software. Uso e Implementação
Todas essas soluções são baseadas na
premissa do trancamento (locking), isto é, Sistemas Operacionais fazem a
proteção de regiões críticas usando-se de distinção entre:
locks. Semáforos de contagem: podem
O problema da seção crítica é variar em um domínio irrestrito. Podem ser
facilmente resolvível em um computador, usados para controlar o acesso a
mas não é tão viável em um ambiente determinado recurso composto por um
multiprocessador, já que a desabilitação de número finito de instâncias.
interrupções em um multiprocessador pode Semáforos binários: Varia somente
ser demorada. entre 0 e 1 e se comportam de maneira
No entanto, muitos sistemas de semelhante aos locks mutex.
computação modernos fornecem instruções Semáforos também são usados para
de hardware especiais que permitem testar e resolver vários problemas de sincronização.
modificar o conteúdo de uma palavra ou Cada semáforo contém um valor
permutar conteúdo de duas palavras inteiro e um ponteiro para uma lista de PCBs.
atomicamente (ou seja, como uma unidade Uma forma de adicionar processos da lista e
impossível de interromper. removê-los da lista, para garantir a espera
limitada, é usando uma fila FIFO, em que o
semáforo contenha ponteiros para a cabeça
Locks Mutex e a cauda da fila. Em geral, qualquer
estratégia de enfileiramento pode ser usada.
As soluções baseadas em hardware
citadas acima, são complicadas e muitas Deadlocks e Inanição
vezes inacessíveis aos programadores de
aplicações. Como alternativa, os projetistas A implementação de um semáforo
de SO constroem ferramentas de software com fila de espera pode fazer com que dois
para resolver isso. ou mais processos fiquem esperando
Locks mutex (ou spinlock) são usados indefinidamente por um evento que pode ser
para proteger regiões críticas, evitando causado apenas por um dos processos em
condições de corrida. espera. Quando tal estado é alcançado,
Desvantagem: requer a espera em dizemos que esses processos estão em
ação (enquanto um processo está em sua deadlock.
Outro problema relacionado aos Existem dois tipos de processos: os
deadlocks é o bloqueio indefinido ou leitores e os gravadores. Se um gravador e
inanição, que ocorre quando os processos algum outro processo (leitor ou gravador)
esperam indefinidamente dentro do acessarem o banco de dados
semáforo. Ele pode ocorrer se remover simultaneamente, pode resultar em caos.
processos da lista associada a um semáforo, Para tirar essa dificuldade, basta
em ordem LIFO (último a entrar, primeiro a garantir que gravadores tenham acesso
sair). exclusivo ao Banco de dados, quando foram
utilizá-lo. Esse problema de sincronização é
Inversão de Prioridades chamado de problema dos leitores-
gravadores. Eles são usados desde sua
Um desafio de scheduling ocorre definição, para testar os novos tipos primitivos
quando um processo de prioridade mais alta de sincronização.
precisa ler ou modificar dados do kernel que Existem variações desse problema,
estão sendo acessados correntemente por mas. No primeiro deles, nenhum leitor deve
um processo de prioridade mais baixa. Já que esperar que outros leitores terminem, só
esses processos são protegidos por lock, o porque tem um gravador esperado. No
processo de prioridade mais alta precisa segundo, se um gravador está esperando,
esperar o de prioridade mais baixa terminar. nenhum novo leitor pode começar a ler.
Se o de baixa prioridade sofrer de Uma solução para qualquer um dos
preempção por causa de um processo de dois problemas pode resultar em inanição. O
prioridade mais alta, isso tornará as coisas primeiro caso, pode causar inanição nos
mais complicadas. gravadores, e o segundo, nos leitores.
Esse problema é conhecido como Esse problema e suas soluções têm sido
inversão de prioridades, e só ocorre em generalizados para fornecer locks de leitores-
sistemas com mais de duas prioridades, gravadores em alguns sistemas. A aquisição
portanto, usar apenas duas prioridades é uma de um desses lock requer a especificação da
solução. Mas essa solução não é o suficiente modalidade do lock: acesso à leitura ou à
para muitos SOs, que resolvem isso gravação.
implementando um protocolo de herança de Vários processos são autorizados a
prioridades, em que todos os processos que adquirirem concorrentemente esses locks na
estão acessando recursos requeridos por um modalidade de leitura, mas só um de
processo de prioridade mais alta, herdam a gravação, já que o acesso é exclusivo para
prioridade mais alta até terminar o uso desses este.
recursos. Quando termina de usar, sua Utilidade locks leitores-gravadores:
prioridade volta ao normal.  Aplicações em que é fácil
identificar processos que apenas
leem dados compartilhados e
Problemas clássicos de processos que apenas gravam
dados compartilhados.
Sincronização  Em aplicações que têm mais
leitores do que gravadores.
O Problema do Buffer Limitado
Problema dos Filósofos Comensais
A inversão de prioridades pode ser
mais do que inconveniente para o Cinco filósofos compartilham uma
Scheduling, pois em sistemas com restrições mesa circula rodeada por cinco cadeiras,
de tempo rígidas, a inversão de prioridades uma para cada. No centro da mesa, há uma
pode fazer com que um processo demore tigela de arroz e a mesa está posta com cinco
mais do que deveria, acarretando, em chopstick individuais. Periodicamente, um
cascata, outras falhas, e resultando em uma filósofo fica com fome e tenta pegar os dois
falha do sistema. chopsticks que estão mais próximos (um a
direita e um a esquerda. Ele não pode pegar
O Problema dos Leitores-Gravadores um que já esteja na mão de um vizinho. Um
filósofo só larga os dois chopsticks depois que
termina de comer.
Esse problema é um clássico problema Sua representação não pode ser
de sincronização, sendo uma simples usada diretamente pelos diversos processos,
representação da necessidade de alocar portanto, uma função definida dentro de um
vários recursos entre diversos processos de monitor pode acessar somente as variáveis
uma forma livre de deadlock e inanição. locais e seus parâmetros formais. Da mesma
Uma solução simples, é representar forma, as variáveis locais são acessadas
cada chopstick com um semáforo. Embora apenas pelas funções locais.
isso garanta que dois vizinhos não comam O construtor monitor assegura que um
simultaneamente, ela é rejeitada por criar um processo de cada vez esteja ativo dentro
deadlock. Se todos ficarem com fome ao dele, mas, até aqui, ele não é
mesmo tempo e pegarem o chopstick suficientemente poderoso para modelar
esquerdo, todos os elementos de chopstick alguns esquemas de sincronização. Para isso,
serão iguais a zero, e quando eles tentarem mecanismos de sincronização adicionais
pegar o chopstick direito, ficará em estado precisam ser definidos. Estes mecanismos são
de suspensão indefinidamente. fornecidos pelo construtor condition. Um
Solução para os deadlock: programador que precise escrever um
 Permitir no máximo quatro filósofos esquema de sincronização personalizado
sentados à mesa simultaneamente. pode definir uma ou mais variáveis do tipo
 Permitir que um filósofo pegue seus condition.
chopstick apenas se os dois
estiverem disponíveis (para isso, Solução para Filósofos Comensais com
usaria seção crítica). Monitor
 Usar solução assímetrica (um
filósofo de número ímpar pega Essa solução impõe a restrição de que
primeiro o chopstick esquerdo e um filósofo só possa pegar seu chopstick se os
depoi o direito, enquanto um dois estiverem disponíveis, sendo possível que
filósofo par pega primeiro o um deles morra de inanição.
esquerdo e depois o direito.
Qualquer solução satisfatória garante a Monitor usando semáforo
possibilidade que um deles morra de fome,
não garantindo deadlock, mas deixando Nesse caso, a exclusão mútua de um
sujeito à inanição. monitor é assegurada.

Monitores Retomando Processos dentro de um monitor

Erros de timing podem ocorrer ao usar Uma solução para determinar qual dos
semáforos. Para lidar com eles, pesquisadores processos suspensos deve ser retomado é usar
desenvolveram construtores de linguagem de a ordem FCFS (primeiro a entrar, primeiro a ser
alto nível. Nesse caso, será mostrado o atendido), para que o processo que tenha
monitor. esperado mais tempo seja retomado
primeiro. Em muitas circunstâncias um
Uso esquema de Scheduling tão simples não é
adequado. Por isso, o construtor de espera
Um tipo de dados abstrato (ADT) condicional pode ser usado.
encapsula dados com um conjunto de O conceito de monitor não garante
funções para operarem sobre esses dados, que a sequência de acesso anterior seja
que são independentes de qualquer seguida.
implementação específica do ADT. Problemas que podem ocorrer:
Um tipo monitor é um ADT que inclui um  Um processo pode acessar um
conjunto de operações – definidas pelo recurso sem antes obter permissão
programador – e que são de exclusão mútua para isso.
dentro do monitor. Ele também declara  Um processo pode nunca liberar
variáveis cujo valores definem o estado de um recurso após ter acesso a ele.
uma instância desse tipo, além dos corpos de  Um processo pode tentar liberar um
funções que operam sobre essas variáveis. recurso que nunca solicitou.
 Um processo pode solicitar o que uma variável inteira precisa ser
mesmo recurso duas vezes, sem atualizada, já que essas operações inteiras
liberá-lo antes. não geram overhead dos lockings. Há
também os lock mutex, para proteger seções
críticas. Usa-se ainda de spinlocks e
Exemplos de Sincronização semáforos.
Em uniprocessadores: a preempção
No Windows do kernel é desativada.
Em multiprocessadores: a preempção
O Windows é um kernel multithread e é ativada.
dá suporte a aplicações de tempo real e a Os spinlocks são usados no kernel
múltiplos processadores. apenas quando um lock é mantido por um
Em um sistema uniprocessado, quando curto tempo. Quando um lock precisa ser
o kernel acessa um recurso global, as mantido por mais tempo, o mais adequado é
interrupções são mascaradas o semáforo ou locks mutex.
temporariamente.
Em sistemas multiprocessados, ele No Solaris
protege o acesso a recursos globais usando
spinlocks. Além disso, o kernel assegura que Fornece locks mutex adaptativos,
uma thread nunca sofra preempção variáveis de condição, semáforos, locks de
enquanto estiver mantendo um spinlocks. leitor-gravador e roletas.
Para a sincronização de threads fora Um mutex adaptativo protege o
do kernel, o Windows oferece objetos acesso a todos os itens de dados críticos. No
despachantes, em que os threads são Solaris ele é usado para proteger apenas os
sincronizados de acordo vários mecanismos dados que são acessados por curtos
diferentes, como locks mutex, semáforos, segmentos de código.
eventos e timers. Os locks de leitor-gravador são usados
Os objetos despachantes podem estar para proteger dados que são acessados
em: frequentemente, mas que são de somente
Estado sinalizado: o objeto está leitura.
disponível e o thread não será bloqueado ao Usa roletas para ordenar a lista de
adquiri-lo. threads em espera para adquirir um mutex
Estado não sinalizado: Objeto não adaptativo ou locks de leitor-gravador.
disponível, e o thread será bloqueado ao Roleta é uma estrutura de fila que
tentar adquiri-lo. contém os threads trancados de um lock.
Um objeto seção crítica é um mutex de
modalidade de usuário que pode ser
adquirido e liberado sem intervenção do Abordagens Alternativas
kernel. Em sistemas multiprocessado, ele usa
primeiro um spinlocks enquanto espera que o À medida que o número de núcleos de
outro thread libere o objeto. Se ele mantiver o processamento aumenta, torna-se cada vez
spin por muito tempo, o thread que está mais difícil projetar aplicações multithreads
tentando obter o objeto alocará então um que não apresentem condições de corrida e
mutex do kernel e abandonará sua CPU. deadlocks.

Sincronização no Linux Memória Transacional

Antes da versão 2.6, o Linux era um Seu conceito teve origem na teoria de
kernel sem preempção. banco de dados, e mesmo assim, é uma
Agora, ele é totalmente preemptível e, estratégia para sincronização de processos.
uma tarefa pode sofrer preempção quando Uma transação de memória é uma
está sendo executada no kernel. sequência de operações atômicas de leitura-
Ele fornece vários mecanismos gravação em memória. Se todas as
diferentes para a sincronização do kernel. A operações de uma transação são
mais simples é um inteiro atômico. Estes são concluídas, a transação da memória é
particularmente eficientes em situações em confirmada. Caso contrário, as operações
são abortadas e revertidas. Os benefícios da
memória transacional podem ser obtidos por
recursos adicionados a uma linguagem de
programação.
A vantagem desse mecanismo no
lugar dos locks é o que o sistema transacional
– e não o desenvolvedor – é responsável por
garantir a atomicidade. Não é possível a
ocorrência de deadlocks.
A memória transacional pode ser
implementada em software (memória
transacional em software – STM) e hardware
(memória transicional em hardware – HTM)

OpenMP

É considerada mais fácil de usar os que


os locks mutex padrão. Desvantagem: os
desenvolvedores de aplicações ainda
devem identificar possíveis condições de
corrida e proteger adequadamente os dados
compartilhados usam a diretiva de
compilador.

Linguagens de Programação Funcionai

A diferença entre linguagens


imperativas e funcionais é que estas não
mantêm o estado.
Várias linguagens funcionais são
usadas hoje em dia, como por exemplo:
Erlang: suporta a concorrência e é fácil
para ser usada no desenvolvimento de
sistemas paralelos.
Scala: é orientada a objetos. Sintaxe
em grande parta semelhante a Java e C#.

Você também pode gostar