Você está na página 1de 37

Programação Concorrente

Aula 01
Prof: André Luis Meneses
Silva
Conteúdo
• O que é
• Motivação
• Conceitos
• Processos
• Threads
• Propriedades
• Safety
• Liveness
Programação Concorrente
[ O que é ]

• “Um programa concorrente é um


conjunto de programas seqüenciais
comuns que são executados em um
paralelismo abstrato” (M.Bem-Ari)
Programação Concorrente
[ O que é ]

• “Um programa concorrente


especifica 2 ou mais processos que
cooperam para realizar uma tarefa.
Processos cooperam através de
comunicação; utilizam variáveis
compartilhadas ou troca de
mensagens“(G. R. Andrews)
Programação Concorrente
[ Motivação ]

• Aproveitar hardware com múltiplos


processadores
• Atender a vários usuários
simultaneamente
• Melhorar o desempenho das
aplicações
• Aumentar a disponibilidade para o
usuário
• Objetos ativos e controle de
atividades
Programação Concorrente
[ Conceitos ]
• Paralelismo
– Processamento simultâneo físico
• Concorrência
– Processamento simultâneo lógico (aparente)
– Requer entrelaçamento (interleaving) de ações
• Processo
– Execução de um programa
• Programa Concorrente
– Vários processos que cooperam para a realização de
uma tarefa
Programação Concorrente
[ Conceitos ]
• Comunicação
– Variáveis compartilhadas
– Passagem de mensagens
• Sincronização
– Exclusão mútua de seções críticas
– Sincronização por condição
• Estado de um programa concorrente
– Consiste dos valores das variáveis (explícitas e
implícitas)
– A execução de um comando muda o estado
• Ações atômicas
– Transformação indivisível de estado
Programação Concorrente
[ Processos ]
• Um processo é um programa que está em
algum estado de execução
• Tem espaço de endereçamento próprio, que é
mapeado pelo S.O. para memória física
• Possui um fluxo de controle ou thread único
• Mantém um contador de programa (PC) que
indica o endereço da próxima instrução
• A MMU (Memory Management Unit) traduz os
endereços lógicos em endereços físicos, que
normalmente não são contíguos (Memória
Virtual)
Programação Concorrente
[ Processos ]

• Espaço de Endereçamento Lógico

Pilha

Espaço de
Endereçamen
to Lógico de Heap
um Processo
Dados Globais

Instruções
Programação Concorrente
[ Processos ]

• Tabela de Processos
– Estado do processo
– Valores dos registradores
– Arquivos abertos
– Alocação de memória
– PID (Process ID)
– UID (User ID)
– GID (Owner’s Group ID)
Programação Concorrente
[ Processos ]

• Estados de um processo
– Executando (Running): Utilizando a
CPU
– Executável ou Pronto (Runnable ou
Ready): Esperando para ser escalonado
para usar a CPU
– Suspenso (Suspended): Recebeu um
sinal para ser suspenso
– Bloqueado (Blocked): Esperando pela
conclusão de algum serviço solicitado ao
S.O.
Programação Concorrente
[ Processos ]

Ativ
o
Bloqueado

Executável Executando
Encerrad
Iniciad o
o
Suspenso
Programação Concorrente
[ Threads ]
• Um processo pode ter mais de uma
Thread (Linha)
• Cada Thread possui contador de
programa e pilha próprios
• Quando um processo é escalonado
para ser executado, uma das
Threads entra em execução
• As Threads compartilham as
variáveis globais do processo
Programação Concorrente
[ Threads ]

Espaço de Endereçamento de um
Processo
Pilha
Thread 1 Thread 2 Thread n
Pilha Pilha Pilha

Contador Contador Contador


de Programa de Programa de Programa

Heap

Variáveis Globais

Instruções
Programação Concorrente
[ Threads ]

• Vantagens sobre processos


compartilhando memória
– São muito mais leves de serem criadas
– A troca de contexto é mais suave pois
compartilha instruções, heap e variáveis
globais
– Facilitam o compartilhamento de
memória
Threads
[ Ciclo de Vida ]
Intervalo de tempo
Dormindo slee
expirou
p
Encerrada
escalonad Término
Criada
a
Pronta Executando
start
interrompi
da
notify wait
Operaçã Operaçã
o notityA o
de E/S ll de E/S
concluíd Esperando iniciada
a
Bloqueada
Threads
[ Sincronização ]

• Sincronizando Threads
– Programação com múltiplas Threads
requer bastante cuidado:
• Acesso / Atualização de variáveis
compartilhadas
• Starvation
• Deadlock
• Acesso a estados inválidos de outros objetos
Threads
[ Sincronização ]
• Problema de acesso a variáveis
compartilhadas
– Várias Threads (representando os depósitos dos
clientes) querendo atualizar (depositar um valor)
uma mesma conta
– Quando uma está lendo o saldo atual, uma outra
Thread pode já ter lido esse valor e calculado o
novo saldo, mas ainda não ter gravado o novo valor
– Se nesse momento a primeira Thread gravar o
valor, o saldo final será igual ao calculado pela
Thread que gravar o novo valor por último
(desconsiderando assim o depósito da Thread que
encerrou primeiro).
– O ideal é impedir que uma operação de depósito
seja iniciada antes da outra encerrar
Threads
[ Sincronização ]
• A sincronização baseia-se na idéia de que
para acessar um método sincronizado ou um
entrar em um bloco sincronizado, é preciso
obter (ou já ter) o lock desse objeto.
• A Thread que conseguir esse lock é a única
autorizada a acessar os recursos
protegidos através de sincronização.
Programação Concorrente
[ Propriedades ]
• Safety: O programa nunca entra em um
estado inconsistente)
• Liveness: Em algum momento o programa
entra em um estado consistente
• Correção Parcial: Se o programa terminar, o
resultado está correto. Caso contrário, nunca
pode dar o resultado correto
• Término: O programa termina
eventualmente
• Ausência de Deadlock: Nunca todos os
processos estarão bloqueados
• Correção Total: O programa sempre
termina e produz o resultado correto
Safety
[ Introdução ]

• Objetos interagindo em múltiplas


Threads normalmente provocam
interferência
• Programas concorrentes devem
possuir 2 propriedades:
– Safety: Nada de mau acontecerá
durante a execução do programa.
– Liveness: Algo de bom acontecerá
durante a execução do programa.
Safety
[ Introdução ]
• Em geral há mais atenção sobre Safety na
engenharia
– É melhor que o programa não faça nada a ter um
comportamento aleatório ou até perigoso
• Liveness está relacionada ao progresso do
programa
• Em alguns casos é melhor obter uma
informação imprecisa a não receber
– Sistemas de Suporte a Decisão, Data Warehouse e
Simulação de Trânsito
• Melhorar a Liveness pode implicar em reduzir
a Safety
Safety
[ Objetos Seguros ]
• Em programa OO, o controle de
interferência é implementado de
classe a classe
• Objetos/variáveis podem entrar
temporariamente em um estado
inconsistente
• Um objeto/variável é considerado
seguro quando:
– Seu estado consistente é sempre
consistente
– Operações não são realizadas enquanto
Safety
[ Objetos Seguros ]

• Há 3 estratégias conservadoras para


projetar objetos/variáveis seguros:
– Imutabilidade: evitar mudanças de
estado
– Sincronização: garantir acesso
exclusivo dinamicamente
– Contenção: garantir acesso exclusivo
estruturalmente
Safety
[ Imutabilidade ]

• Variáveis de instância constantes


(final em Java)
• Encapsulamento
• Não requer sincronização
• Classes sem estado (stateless)
– Como não há estado, não há
interferência
Safety
[ Sincronização ]

• Um Objeto/variável sempre está


pronto para sofrer modificações,
mesmo quando ainda está no meio
do processamento de alguma
• Acesso a estados inconsistentes
devem ser evitados:
– Conflitos de leitura/escrita: vários lêem
enquanto um escreve
– Conflitos de escrita/escrita: vários lêem
e escrevem ao mesmo tempo
Safety
[ Sincronização ]

• No contexto de OO, podemos ter:


– Sincronização Total
• Objetos totalmente sincronizados. Podem
fazer apenas uma operações por vez

– Sincronização Parcial
• Parte do objeto é sincronizado. Somente
métodos sincronizados são travados
Safety
[ Contenção ]

• Baseia-se na idéia de manter referências


únicas para objetos internos isolados dos
demais.
• São acessados apenas através de métodos
sincronizados do objeto no qual estão
contidos, estando, portanto, protegidos.

interno1 subinterno1

externo1

interno2
Safety
[ Contenção ]

• Recursos Exclusivos
– Garante que somente um objeto por vez
é “proprietário” do recurso exclusivo.
Porém, a propriedade de um recurso
pode mudar
– Semelhanças com objetos físicos:
• Se você tem um, então pode usá-lo
• Se você tem um, ninguém mais pode tê-lo
• Se você da um para alguém, então deixa de
tê-lo
• Se você destrói um, ninguém nunca mais o
Safety
[ Contenção ]

– É preciso definir um protocolo que


garanta a exclusividade do recurso

null

null servi
ço 1
vizinho vizinho
servi servi
ço 0 ço 2
vizinho vizinho
servi Recu
ço 3 rso
null
Liveness
[ Introdução ]
• Projetos baseados em combinações
de Imutabilidade, Sincronização e
Contenção são abordagens simples,
rápidas e de fácil entendimento para
o desenvolvimento de programas
concorrentes OO
• Porém, essas técnicas nem sempre
são a melhor solução
• Utilização de Sincronização pode
provocar problemas de Liveness
(eficiência)
Liveness
[ Falhas de Liveness ]

• São tão sérias quanto falhas de


Safety
• São mais difíceis de identificar e
evitar durante o projeto
• Tipos de falhas
– Contenção: uma thread, apesar de
estar pronta para executar, não executa
porque outra tomou recursos (também
conhecida como starvation ou
adiamento infinito)
Liveness
[ Falhas de Liveness ]
– Dormência: uma thread não pronta
falha ao tentar passar para esse estado.
– Deadlock: duas ou mais threads
bloqueiam-se em um ciclo vicioso
enquanto tentam acessar travas
sincronizadas necessárias para
continuar suas atividades
– Término prematuro: uma thread é
parada ou encerrada prematuramente
Liveness
[ Análise de Variáveis de Instância ]

• Através de análise de variáveis e


métodos, é possível identificar
oportunidades para reduzir a
sincronização
• Muitas vezes, a proteção
implementada é exagerada
Liveness
[ Análise de Variáveis de Instância ]

• Acesso
– Métodos de acesso podem deixar de ser
sincronizados para permitir leitura
durante a escrita
– Condições para remover a
sincronização:
• A variável não pode assumir valores ilegais
durante a execução dos métodos
• Atribuição atômica
Liveness
[ Análise de Variáveis de Instância ]

• Atualização
– Métodos de atualização podem abdicar
da sincronização quando satisfaz, além
das condições para acesso:
• Valor da variável permanece consistente em
todas as possíveis situações (Ex: atributo
temperatura sendo atualizado
constantemente por múltiplas threads)
• Não requer ações especiais sincronizadas
para certos valores assumidos pelas
variáveis (Ex: reconstruir uma estrutura de
dados após atingir um tamanho)
Referências
• Concurrent Programming - Hartley
(capítulo 1)
• Concurrent Programming in Java -
Lea (capítulo 1, 2 e 3)