64
1 Programação Concorrente JAVA Prof. Alexandre Monteiro Recife

Programação Concorrente JAVA

Embed Size (px)

DESCRIPTION

Programação Concorrente JAVA. Prof. Alexandre Monteiro Recife. Contatos. Prof. Guilherme Alexandre Monteiro Reinaldo Apelido: Alexandre Cordel E-mail/ gtalk : [email protected] [email protected] Site: http://www.alexandrecordel.com.br/fbv Celular: (81) 9801-1878. Conteúdo. - PowerPoint PPT Presentation

Citation preview

Page 1: Programação Concorrente JAVA

1

Programação Concorrente JAVA

Prof. Alexandre Monteiro

Recife

Page 2: Programação Concorrente JAVA

Contatos

Prof. Guilherme Alexandre Monteiro Reinaldo

Apelido: Alexandre Cordel

E-mail/gtalk: [email protected]

[email protected]

Site: http://www.alexandrecordel.com.br/fbv

Celular: (81) 9801-1878

Page 3: Programação Concorrente JAVA

Conteúdo

O que é

Motivação

Conceitos

Processos

Threads

Propriedades

Safety

Liveness

Threads em JAVA

Page 4: Programação Concorrente JAVA

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)

Page 5: Programação Concorrente JAVA

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)

Page 6: Programação Concorrente JAVA

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 da CPU para o usuário

Objetos ativos e controle de atividades

Programas paralelos

Page 7: Programação Concorrente JAVA

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 (running)

Programa Concorrente

•Vários processos que cooperam para a realização de uma tarefa ou mais tarefas

Page 8: Programação Concorrente JAVA

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

Page 9: Programação Concorrente JAVA

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)

Page 10: Programação Concorrente JAVA

Programação Concorrente[ Processos ]

Espaço de Endereçamento Lógico

Instruções

Dados Globais

Espaço de Endereçamento

Lógico de um Processo

Pilha

Heap

Page 11: Programação Concorrente JAVA

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)

Page 12: Programação Concorrente JAVA

Programação Concorrente[ Processos ]

Estados de um processo

1. Iniciado (Start): processo criado

2. Executando (Running): Utilizando a CPU

3. Executável ou Pronto (Runnable ou Ready): Esperando para ser escalonado para usar a CPU

4. Suspenso (Suspended): Recebeu um sinal para ser suspenso

5. Bloqueado (Blocked): Esperando pela conclusão de algum serviço solicitado ao S.O.

6. Encerrado (Dead): processo morto

Page 13: Programação Concorrente JAVA

Programação Concorrente[ Processos ]

Executando

Suspenso

Executável

Bloqueado

Encerrado

Iniciado

Ativo

Page 14: Programação Concorrente JAVA

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

Page 15: Programação Concorrente JAVA

Programação Concorrente[ Threads ]

Espaço de Endereçamento de um Processo

Instruções

Variáveis Globais

Pilha

Heap

Pilha

Contadorde Programa

Thread 1

Pilha

Contadorde Programa

Thread 2

Pilha

Contadorde Programa

Thread n

Page 16: Programação Concorrente JAVA

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

Page 17: Programação Concorrente JAVA

Threads[ Ciclo de Vida ]

Criada

Pronta Executando

Esperando

Dormindo

Encerrada

Bloqueada

Operaçãode E/Siniciada

Término

4.sleep()

5.notify()5.notityAll()

Operaçãode E/Sconcluída

2.start()

Intervalo de tempo expirou

escalonada

interrompida

1.new Thread()

3.run()

6.stop()

4.wait()

Page 18: Programação Concorrente JAVA

Threads[ Sincronização ]

Sincronizando Threads

•Programação com múltiplas Threads requer bastante cuidado:

- Acesso / Atualização de variáveis compartilhadas- Starvation (processo nunca é executado)- Deadlock (impasse e dois ou mais processos ficam

impedidos de continuar suas execuções e ficam bloqueados)

- Acesso a estados inválidos de outros objetos

Page 19: Programação Concorrente JAVA

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.

Page 20: Programação Concorrente JAVA

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

Page 21: Programação Concorrente JAVA

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.

Page 22: Programação Concorrente JAVA

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

Page 23: Programação Concorrente JAVA

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

Page 24: Programação Concorrente JAVA

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

Page 25: Programação Concorrente JAVA

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.

Page 26: Programação Concorrente JAVA

Safety [ Contenção ]

•É preciso definir um protocolo que garanta a exclusividade do recurso

serviço 2serviço 0

serviço 3

serviço 1vizinho

vizinho vizinho

vizinho

null

null

null

Recurso

Page 27: Programação Concorrente JAVA

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)

Page 28: Programação Concorrente JAVA

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

Page 29: Programação Concorrente JAVA

29

Threads JAVA

Page 30: Programação Concorrente JAVA

Definições Básicas

Threads são sub-procesos no sistema operacional.

É menos custoso gerenciar threads do que processos.

As linguagens Java e Ada possuem funcionalidades MULTITHREADING na própria estrutura da linguagem.

C e C++ necessitam de biblioteca especifica para processamento MULTITHREADING •Posix p_thread

Page 31: Programação Concorrente JAVA

Diagrama de Estados Thread JavaO diagrama mostra os estados de uma thread de Java pode estar e alguns métodos que podem ser usados para mudar de um estado para outro.

Page 32: Programação Concorrente JAVA

New Thread

Inicialização do thread - feita através do construtor Thread().

class MyThreadClass extends Thread{

...

}

...

MyThreadClass myThread = new MyThreadClass();

Neste estado, nenhum recurso do sistema foi alocado para o thread ainda, assim, a partir daqui, tudo que você pode fazer é um start(), para ativar o thread, ou um stop(), para "matá-lo".

A chamada de qualquer outro método não faz sentido e levantará a exceção IllegalThreadStateException.

Page 33: Programação Concorrente JAVA

Runnable

Este é o estado em que o thread está pronto para rodar. O método start() requisita os recursos do sistema necessários para rodar o thread e chama o seu método run().

O método run() é a "alma" de um thread; é neste método que definimos o que o thread vai executar.

Thread myThread = new MyThreadClass();

myThread.start();

Falamos em "Runnable", ao invés de "Running", porque o thread pode não estar realmente sendo executado. Imagine um computador com um único processador - seria impossível executar todos os threads "Runnable" ao mesmo tempo. O que ocorre é que a CPU deve ser escalonada entre os vários threads.

Quando um thread está "Running", ele está também "Runnable", e, as instruções do seu método run() é que estão sendo executadas pela CPU.

Page 34: Programação Concorrente JAVA

Not Runnable

O estado "Not Runnable" significa que o thread está impedido de executar por alguma razão. Existem 4 maneiras através das quais um thread ir para o estado "Not Runnable":

•Alguém manda-lhe a mensagem suspend().

•Alguém manda-lhe a mensagem sleep().

•O thread bloqueia, esperando por I/O.

•O thread usa seu método wait() para esperar por uma variável de condição.

Page 35: Programação Concorrente JAVA

Not Runnable

O exemplo abaixo coloca “myThread” para dormir por 10 segundos...

Thread myThread = new MyThreadClass();

myThread.start();

try {

myThread.sleep(10000);

} catch (InterruptedException e){

}

Page 36: Programação Concorrente JAVA

Not Runnable

Cada uma destas maneiras tem a sua forma específica de sair do estado "Not Runnable".

•Se o thread foi suspenso, alguém precisa mandar-lhe a mensagem resume().

•Se o thread foi posto para dormir, ele voltará a ser "Runnable" quando o número de milisegundos determinado passar.

•Se o thread está bloqueado, esperando por I/O, a I/O precisa ser completada.

•Se o thread está esperando por uma variável de condição, o objeto que a "segura" precisa liberá-la, através de um notify() ou de um notifyAll()

Page 37: Programação Concorrente JAVA

Dead

Um thread pode morrer de "causas naturais" (quando o seu método run() acaba normalmente) ou pode ser morto (AssAssINAdO pelo método stop()).

Thread myThread = new MyThreadClass(); myThread.start();

public void run() { int i = 0; while (i < 100) {

i++; System.out.println("i = " + i);

} }

Este thread vai morrer naturalmente quando o loop do run() acabar.

Page 38: Programação Concorrente JAVA

Dead

O que vai acontecer com este thread?

Thread myThread = new MyThreadClass(); myThread.start();

try { Thread.currentThread().sleep(10000);

} catch (InterruptedException e){ } myThread.stop();

Page 39: Programação Concorrente JAVA

Método yield()

O método yield()

Cede a CPU para outros threads

Page 40: Programação Concorrente JAVA

Thread em Java

Em Java, threads são implementadas como uma CLASSE

•Pacote java.lang.Thread

•É uma extensão da classe Thread

•Contrutores:- public Thread (String nome_da_thread);- public Thread ( ); // o nome sera Thread-#

• Thread-1, Thread-2,…

Page 41: Programação Concorrente JAVA

Principais Métodos

•run(): é o método que executa as atividades de uma THREAD. Quando este método finaliza, a THREAD também termina.

•start(): método que dispara a execução de uma THREAD. Este método chama o método run( ) antes de terminar.

•sleep(int x): método que coloca a THREAD para dormir por x milisegundos.

Page 42: Programação Concorrente JAVA

Principais Métodos

•join( ): método que espera o término da THREAD para qual foi enviada a mensagem para ser liberada.

•interrupt( ): método que interrompe a execução de uma THREAD.

•interrupted( ): método que testa se uma THREAD está ou não interrompida.

Page 43: Programação Concorrente JAVA

Estados de uma Thread em Java

nascimento

pronta

executando

esperando dormindo mortabloqueada

start( )

Alocar um processador

wait( )sleep( )

Fim do Método run( )

E/S

Fim da E/Snotify( )

notifyAll( )

Término do tempo de dormida

run( )

stop( )

Page 44: Programação Concorrente JAVA

Prioridade de Thread

Em Java, a prioridade é determinada com um inteiro entre 1 e 10.

A prioridade padrão é o valor 5.

10 é a maior prioridade e 1 é a menor.

A THREAD herda a prioridade da THREAD que acriou.

void setPriority(int prioridade);

int getPriority( );

Page 45: Programação Concorrente JAVA

Algoritmo de Escalonamento

Prioridade 10

Prioridade 1

Prioridade 9

Prioridade 8

Prioridade 2

Prioridade 3

.

.

.

A B

C

D E F

G

Page 46: Programação Concorrente JAVA

Exercício 01

O programa cria 04 threads e as coloca para dormir.

ThreadBasica é uma extensão da classe Thread.

Page 47: Programação Concorrente JAVA

Exercício 01

•Analise como se chama o método sleep().

•Crie n THREADs, onde n é definido pelo usuário.

•Utilize o método join no main para esperar as THREADs terminarem. try { uma_thread.join( ); // uma_thread.join(tempo)

… }catch (InterruptedException e) {

… }

Page 48: Programação Concorrente JAVA

Escalonamento de Threads

Prioridade 10

Prioridade 1

Prioridade 9

Prioridade 8

Prioridade 2

Prioridade 3

.

.

.

A B

C

D E F

G

Page 49: Programação Concorrente JAVA

Exercício 02

Prioridades de Threads

Utilize o método setPriority(int) para mudar a prioridade de threads

•Utilize 01 thread com prioridade 1, 01 com prioridade 09 e as outras com prioridade 05.

•Faça com que uma das threads de alta prioridade durma por 10 ms antes de terminar.

•Faça com que outra thread de alta prioridade faça uma entrada de dado.

Page 50: Programação Concorrente JAVA

Exercício 03

Problema Produtor X Consumidor

- Com buffer de tamanho 1.

- Variáveis compartilhadas.

- A solução do problema seria utilizar-se duas THREADS: 01 consumidor e 01 produtor.

- O que ocorre se não houver sincronização entre a leitura e escrita?

Page 51: Programação Concorrente JAVA

Exercício 04

Problema do Produtor X Consumidor com sincronização do Buffer.

Em Java, a sincronização entre threads é feita através do conceito de monitores.

Monitor é um agrupamento de funções, cujas execuções não podem se dar de forma concorrente.

Page 52: Programação Concorrente JAVA

Exercício 04

Utilizar os métodos multuamente excludentes de um objeto como do tipo synchronized em Java.

Utilizar os métodos wait( ) e notify( ) para bloquear e liberar, respectivamente, as threads.

Resolver o problema de Produtor-Consumidor.

Page 53: Programação Concorrente JAVA

A interface Runnable

A solução encontrada em Java foi a utilização de uma interface: Runnable

•No caso, tem-se de implementar esta interface, que possui o método run( ).

public class Filho extends Pai implements Runnable

•Ao implementar uma interface, a classe se capacita a ser tratada como se fosse um objeto do tipo da inteface implementada.

- Se a classe Filho implementar a interface Runnable, ela pode ser tratada como tal.

Page 54: Programação Concorrente JAVA

A interface Runnable

Para utilizar multithreads em Java é necessário instanciar um objeto de uma classe que estende a classe básicaThread, certo?

Uma vez que Java não possui herança múltipla, como eu posso utilizar um objeto, cuja classe já é derivada, como no caso da ClasseThread? public class Filho extends Pai extends Thread {

……………….

} // isto nao eh possivel em Java

Page 55: Programação Concorrente JAVA

A interface Runnable

Cria-se uma thread (Classe Thread), passando para o seu construtor uma referência do objeto que implementa a interface Runnable.

Thread uma_Thread = new Thread(Runnable obj_thread)

Thread uma_Thread = new Thread(Runnable obj_thread, String nome_da_thread)

Page 56: Programação Concorrente JAVA

Exercício 5

Crie um programa onde o usuário possa escolher a quantidade de processos a serem criados para execução em concorrência.

Estes devem ser nomeados e atribuída prioridades valores de 1 até um valor máximo 10, passado para cada um deles.

Quando o processo atingir o número correspondente a metade do valor máximo do número de processos, deve entrar em espera de um tempo calculado de maneira randômica entre 1 e 5 segundos e posteriormente ser liberado. O programa deve ter um menu com as seguintes opções: 1) Criação de processos (qtd e nomes)2) Prioridades dos processos (int de 1 a 10)

Page 57: Programação Concorrente JAVA

Exercício 6 Veja a classe a seguir

É uma classe que implementa Runnable e, no método run(), apenas imprime dez mil números.

Vamos usá-las duas vezes para criar duas threads e imprimir os números duas vezes simultaneamente:

Page 58: Programação Concorrente JAVA

Exercício 6

Page 59: Programação Concorrente JAVA

Exercício 6 Se rodarmos esse programa, qual será a saída? De um a

mil e depois de um a mil? Provavelmente não, senão seria sequencial. Ele imprimirá 0 de t1, 0 de t2, 1 de t1, 1 de t2, 2 de t1, 2 de t2 e etc? Exatamente intercalado?

Na verdade, não sabemos exatamente qual é a saída.

Rode o programa várias vezes e observe: em cada execução a saída é um pouco diferente.

Depois mude a prioridade e veja como ocorre a execução.

Page 60: Programação Concorrente JAVA

Exercício 6 O problema é que no computador existe apenas um

processador capaz de executar coisas. E quando queremos executar várias coisas ao mesmo tempo, e o processador só consegue fazer uma coisa de cada vez? Entra em cena o escalonador de threads.

O escalonador (scheduler), sabendo que apenas uma coisa pode ser executada de cada vez, pega todas as threads que precisam ser executadas e faz o processador ficar alternando a execução de cada uma delas.

A ideia é executar um pouco de cada thread e fazer essa troca tão rapidamente que a impressão que fica é que as coisas estão sendo feitas ao mesmo tempo.

Page 61: Programação Concorrente JAVA

Exercício 6 O escalonador é responsável por escolher qual a próxima thread

a ser executada e fazer a troca de contexto (context switch). Ele primeiro salva o estado da execução da thread atual para depois poder retomar a execução da mesma. Aí ele restaura o estado da thread que vai ser executada e faz o processador continuar a execução desta. Depois de um certo tempo, esta thread é tirada do processador, seu estado (o contexto) é salvo e outra thread é colocada em execução. A troca de contexto é justamente as operações de salvar o contexto da thread atual e restaurar o da thread que vai ser executada em seguida.

Quando fazer a troca de contexto, por quanto tempo a thread vai rodar e qual vai ser a próxima thread a ser executada, são escolhas do escalonador. Nós não controlamos essas escolhas (embora possamos dar "dicas" ao escalonador). Por isso que nunca sabemos ao certo a ordem em que programas paralelos são executados.

Page 62: Programação Concorrente JAVA

Exercício 6

Todo esse processo é feito automaticamente pelo escalonador do Java (e, mais amplamente, pelo escalonador do sistema operacional). Para nós, programadores das threads, é como se as coisas estivessem sendo executadas ao mesmo tempo.

Page 63: Programação Concorrente JAVA

Referências

Concurrent Programming - Hartley (capítulo 1)

Concurrent Programming in Java - Lea (capítulo 1, 2 e 3)

Page 64: Programação Concorrente JAVA

64

Programação Concorrente JAVA

Prof. Alexandre Monteiro

Recife