especificação de...

12

Click here to load reader

Upload: phungdieu

Post on 23-Nov-2018

212 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Especificação de Concorrência/Paralelismogec.di.uminho.pt/lesi/ap10203/Aula05Concorrência.pdf · Programação concorrente em JAVA Segurança – nada de mau deve acontecer num

Arquitecturas Paralelas I Computação Paralela em Larga Escala

LESI - 4º Ano

Especificação de Concorrência/Paralelismo

(gec.di.uminho.pt/lesi/ap10203/Aula05Concorrência.pdf)

João Luís Ferreira Sobral Departamento do Informática

Universidade do Minho

Outubro 2002

Page 2: Especificação de Concorrência/Paralelismogec.di.uminho.pt/lesi/ap10203/Aula05Concorrência.pdf · Programação concorrente em JAVA Segurança – nada de mau deve acontecer num

Arquitecturas Paralelas I 2 © João Luís Sobral 2002

Especificação de Concorrência/Paralelismo

Baseada nos conceitos de fio de execução (thread)/ processo • Fio de execução versus processo

• Paralelismo lógico versus paralelismo físico

• Preempção de fios de execução

• Escalonamento dos fios com base em prioridades

Vantagens da utilização da concorrência: • Programas que requerem a execução de várias tarefas (reactivos)

• Existem objectos dos mundo real que são activos

• Melhora a disponibilidade de serviços

• Possibilita as mensagens/invocações de métodos assíncronas

• Tira partido do paralelismo quando existem vários CPU

• Concorrência requerida (em Java várias classes executam de forma

concorrente, ex. Swing, applet, beans)

Limitações da concorrência

• Segurança (safety) – inconsistências na execução de programas

• Vivacidade (liveness) – impasses na execução de programas

• Introduz não determinismo na execução dos programas

• Em sistemas OO existem menos actividades assíncronas que objectos

• Pouco útil na execução local de métodos, num modelo chamada/resposta

• Introduz uma sobrecarga devido à criação, escalonamento e sincronização dos fios de execução

Page 3: Especificação de Concorrência/Paralelismogec.di.uminho.pt/lesi/ap10203/Aula05Concorrência.pdf · Programação concorrente em JAVA Segurança – nada de mau deve acontecer num

Arquitecturas Paralelas I 3 © João Luís Sobral 2002

Especificação de Concorrência/Paralelismo

Em aplicações tradicionais • Modelos de fork/join, cobegin/coend, e parfor. A sincronização é

efectua com semáforos, barreiras ou monitores.

• Processos activos (CSP), que efectuam processamento através de um corpo activo, interactuando através da passagem de mensagens. A passagem de mensagens pode ser síncrona com bloqueio, síncrona sem bloqueio ou assíncrona.

Em aplicações orientadas ao objecto • Os modelos tradicionais pressupõem um modelo de invocações

síncronas de métodos, onde o cliente fica bloqueado enquanto o método é executado pelo servidor, mesmo que não exista um valor de retorno.

• Quando o método invocado não retorna um valor pode ser efectuada

uma invocação assíncrona, podendo o cliente prosseguir a execução em simultâneo com a execução do método no servidor.

• Quando existe um valor de retorno as invocações também podem ser

assíncronas, existindo, no entanto, três alternativas para o retorno do resultado da operação:

1. Síncrona diferida - O cliente efectua uma segunda invocação ao

servidor para obter o resultado. 2. Com chamada de retorno – O servidor efectua uma invocação de

um método pré-definido do cliente, quando a execução terminou. 3. Com futuros – A invocação é delegada a outro objecto que

armazena o resultado da operação.

tempo

Cliente Servidor tarefa()

resultado()

Cliente Servidor tarefa()

resultado()

Cliente Futurotarefa()

resultado()

Servidor

tarefa()

Page 4: Especificação de Concorrência/Paralelismogec.di.uminho.pt/lesi/ap10203/Aula05Concorrência.pdf · Programação concorrente em JAVA Segurança – nada de mau deve acontecer num

Arquitecturas Paralelas I 4 © João Luís Sobral 2002

Programação concorrente em JAVA

JAVA é das poucas linguagens com suporte à programação concorrente

Classe java.lang.Thread: • Thread(Runnable r); // construtor da classe• start(); // cria um fio de execução e invoca r.run()• join(); // espera pelo fim da execução do fio• sleep(int ms); // suspende o fio de execução• setPriority(int Priority); // altera a prioridade

Interface Runnable

• Deve ser implementado por todas as classes pretendam ser directamente executadas por um fio de execução.

• O método run() contém o código a executar pelo fio de execução.

interface Runnable {public void run();

}

Exemplo: • Criar dois fios de execução que incrementam cada um o seu contador e

que executam em simultâneo:

public class Cont extends Thread {// implícito: implements Runnable

public Cont() { }public void run() {

for (int i=0; i<100; i++) {System.out.println(“ i= “ + i);

}}

}

• Execução sequencial: ...new Cont().run();new Cont().run();... // join

• Execução concorrente:

...new Cont().start();new Cont().start();

// ou new Cont().run();... // join, para esperar pelo fim da execução

Page 5: Especificação de Concorrência/Paralelismogec.di.uminho.pt/lesi/ap10203/Aula05Concorrência.pdf · Programação concorrente em JAVA Segurança – nada de mau deve acontecer num

Arquitecturas Paralelas I 5 © João Luís Sobral 2002

Programação concorrente em JAVA

Segurança – nada de mau deve acontecer num programa

Vivacidade – deve acontecer algo de bom num programa

Exemplo de falta de segurança:

• execução do método inc() por dois fios em simultâneo pode originar um valor incoerente da variável ct

public class Cont {

protected int ct;public Cont() { ct=0; }public void inc() { ct = ct + 1; }

}

Palavras reservadas para especificar sincronização

• synchronized metodo() { ... }

// metodo tem o acesso exclusivo ao objecto

• synchronized (umObj) { ... }// obtém o acesso exclusivo a umObj

Cada objecto é um monitor. Métodos da classe Object:

• wait() – espera pelo acesso ao monitor

• wait(int timeout) – wait, com temporização

• notify() – acorda um fio à espera de acesso

• notifyAll() – acorda todos os fios à espera

Exemplo de falta de vivacidade (deadlock): execução de método inc() por dois fios em simultâneo em objectos com referências cruzadas:

Obj1: .... void syncronized inc() {

obj2.inc()} .... Obj2: ... void syncronized inc() {

obj1.inc()}

Page 6: Especificação de Concorrência/Paralelismogec.di.uminho.pt/lesi/ap10203/Aula05Concorrência.pdf · Programação concorrente em JAVA Segurança – nada de mau deve acontecer num

Arquitecturas Paralelas I 6 © João Luís Sobral 2002

Programação concorrente em JAVA

Padrões de desenho para melhorar a segurança • Objectos imutáveis ou sem estado, uma vez que não é necessário

sincronizar o acesso estes objectos (ex. Classe String)

Ex1: class Relay {

private Server srv; // fixoRelay(Server s) { srv=s; }void do_it() { srv.do_it(); }

} Ex2:

...public int[] sort(int[] arr) {

int[] copy = arr.clone(); // cópia local// sortreturn(copy);

}

• Objectos completamente sincronizados ou com sincronização parcial. Ex1: Variáveis de classe

class Cont {

private static int contadores;void inc() {

synchronized(getClass()) {contadores++;

}}....

}

Ex2: sincronização parcial class Cell {

private int val;private Cell next;...public int synchronized getValue() {

return(val);}public void synchronized setValue(int vl) {

val=vl;}public Cell getNext() { return(next); }

}

• Objectos contidos em outros objectos (ver relay)

Page 7: Especificação de Concorrência/Paralelismogec.di.uminho.pt/lesi/ap10203/Aula05Concorrência.pdf · Programação concorrente em JAVA Segurança – nada de mau deve acontecer num

Arquitecturas Paralelas I 7 © João Luís Sobral 2002

Programação concorrente em JAVA

Padrões de desenho para melhorar a vivacidade • Os métodos que apenas acedem ao estado do objecto geralmente não

necessitam de ser sincronizados (excepto para double e long) • Não é necessário sincronizar as variáveis que são escritas apenas uma

vez:

Ex: ...

void setEnd() { end = True; } ...

• Utilizar sempre que possível a sincronização separada, para acesso a

cada parte do estado (ou dividir o estado em dois objectos).

Ex: class doisPontos {

Ponto p1, p2;public void movexp1(int x) {

synchronized (p1) {p1.movex(x);

}}public void movexp2(int x) {

synchronized (p2) {p2.movex(x);

}}

}

• Estruturas de dados ligadas podem utilizar fechos separados para a inserção e para a remoção.

• Os recursos devem ser acedidos sempre pela mesma ordem para

minimizar os impasses.

Ex:

public void update() {synchronized(obj1) {

synchronized(obj2) {... // do update

}}

}

Page 8: Especificação de Concorrência/Paralelismogec.di.uminho.pt/lesi/ap10203/Aula05Concorrência.pdf · Programação concorrente em JAVA Segurança – nada de mau deve acontecer num

Arquitecturas Paralelas I 8 © João Luís Sobral 2002

Acções Dependentes do Estado dos Objectos

Que acção tomar quando um objecto não pode satisfazer um pedido?

• Ignorar o pedido • Retornar uma indicação de falha (excepção?) • Suspender o cliente até que a condição se verifique • Tomar uma acção provisória • Prosseguir por forma a poder repor o estado se algo correr mal • Repetir a acção até ser possível executá-la

Estratégias pessimistas e estratégias optimistas

Representação lógica do estado versus representação física do estado

• Estado lógico: normalmente definido por predicados: expressões Booleanas em função do estado (ex. buffer cheio, meio e vazio)

• O estado lógico pode ser representado explicitamente em variáveis

Suspensão do cliente através de guardas

• Métodos wait(), notify() e notifyAll() da classe Object

• Exemplo1 (wait()) public class GuardedClass {

protected boolean cond=false;protected synchronized void awaitC() {

while(!cond) {try { wait(); }catch (InterruptedException e) {}

}}public synchronized void guardedAction() {

awaitC();// ...

}public synchronized void setCond() {

cond=true;notifyAll();

}}

• Exemplo2 (espera activa – pouco eficiente)

protected void spinWaitC() {while(!cond) { Thread.yield(); }

}

• Problemas com monitores encadeados: wait() apenas liberta o fecho

desse monitor

Page 9: Especificação de Concorrência/Paralelismogec.di.uminho.pt/lesi/ap10203/Aula05Concorrência.pdf · Programação concorrente em JAVA Segurança – nada de mau deve acontecer num

Arquitecturas Paralelas I 9 © João Luís Sobral 2002

Implementação de Invocações Assíncronas de Métodos

Invocação assíncrona sem valor de retorno

• Implementada através de um padrão comando, onde o comando é executado em paralelo com o cliente. Os parâmetros do comando são passados no seu construtor.

• A activação do comando pode ser efectuada pelo cliente ao pelo próprio

comando.

• Activação pelo cliente:

public class FileWriter extends Thread {private String nm;private byte[] d;

public FileWriter(String n, byte data[]) {nm = n;d = data;

}public void run() {

writeBytes(nm,d);}

}

// código do cliente(new FileWriter(“Pic”,rawPicture)).start();

• Activação pelo servidor

public class FileWriter extends Thread {

private String nm;private byte[] d;

public FileWriter(String n, byte data[]) {nm = n;d = data;start();

}public void run() {

writeBytes(nm,d);}

}

// código do clientenew FileWriter(“Picture”,rawPicture);

Page 10: Especificação de Concorrência/Paralelismogec.di.uminho.pt/lesi/ap10203/Aula05Concorrência.pdf · Programação concorrente em JAVA Segurança – nada de mau deve acontecer num

Arquitecturas Paralelas I 10 © João Luís Sobral 2002

Implementação de Invocações Assíncronas de Métodos

Invocação assíncrona com valor de retorno: como esperar pelo resultado operação realizada por um fio de execução?

Síncrona diferida - Método Thread.join()

r = new Service().start();// .. doWork();r.join();r.getResult();

Futuros

• É utilizado um objecto que irá conter o resultado da operação e que bloqueia o

cliente caso seja requerido o valor antes de estar disponível. Este objecto deve ser partilhado pelo comando e pelo cliente. É implementado através de um Join.

class Future extends Thread {

private Task tk=null;

public Future(Task tsk) {tk = tsk;start();

}public Task getResult() {

join();return(tk);

}public void run() {

tk = do_task(); // realiza a tarefa}

}

Chamadas de retorno

public interface Client {public void opOK(Task);

}

class OPCallBack extends Thread {private Client cl=null;private Task tk=null;

public OPCallBack(Task tsk, Client clk) {tk = tsk;cl = clkstart();

}public run() { cl.opOK(do_task()); }

}

Page 11: Especificação de Concorrência/Paralelismogec.di.uminho.pt/lesi/ap10203/Aula05Concorrência.pdf · Programação concorrente em JAVA Segurança – nada de mau deve acontecer num

Arquitecturas Paralelas I 11 © João Luís Sobral 2002

Implementação de Invocações Assíncronas de Métodos

.Net - Invocação assíncrona sem valor de retorno

• A invocação assíncrona de métodos é directamente suportada em .Net remoting.

• A invocação de métodos sem valor de retorno (One Way) é efectuada marcando o método OneWay e utilizando um delegate para efectuar a invocação.

public class BaseObject {

[OneWay]public void writeBytes(string, int);...

}

// delegate para uma função void xxx(string,int)delegate void writeBytesDelegate(string, int);

static void Main(string[] args) {

ob = new BaseObject;

// cria um delegate para ab.writeByteswriteBytesDelegate wbd =

new writeBytesDelegate(ob.writeBytes);

// inicia a invocaçãoIAsyncResul as =

wbd.BeginInvoke(“Pic”,rawPic,null,null);

// EndInvoke() retorna imediatamentewbd.EndInvoke(as);

}

.Net - Síncrona diferida / Futuros

delegate int serviceDelegate();

public static int service() {// ...

}

static void Main(string[] args) {serviceDelegate dl =

new serviceDelegate(service);IAsyncResult ar = dl.BeginInvoke(null,null);// ... doWork();int res = dl.EndInvoke();

}

Page 12: Especificação de Concorrência/Paralelismogec.di.uminho.pt/lesi/ap10203/Aula05Concorrência.pdf · Programação concorrente em JAVA Segurança – nada de mau deve acontecer num

Arquitecturas Paralelas I 12 © João Luís Sobral 2002

Programação Concorrente/Paralela

Exercícios

1 Codificar e executar o programa exemplo dos dois contadores em paralelo. 2 Desenvolver um programa que implemente um relógio, com uma precisão

de segundos e que execute em simultâneo com o resto do programa. Utilize o seguinte método:

void sleep(miliseconds) throws InterruptedException

3 Implemente um contador com operações de incremento e decremento, que nunca fique inferior a zero, nem superior a 100. Implemente três versões distintas: com indicação de falha, métodos guardados com base no estado físico e métodos guardados com base no estado lógico. Escreva também um programa com dois fios de execução um que incrementa o contador e outro que decrementa o contador, para efectuar testes a esta classe.

Nota: Na versão com indicação da falha, crie uma nova excepção:

public class CannotIncException extends Exception {} que pode ser gerada através de:

throw new CannotIncException();

4 Desenvolva um programa que execute os contadores da alínea 1) em objectos servidores remotos, executando em paralelo.

5 Altere o programa anterior por forma a que o objecto que cria os contadores

seja notificado do fim da contagem (i.e. com Callback).

6 Repita o exercício 4, mas agora em .Net, utilizando um delegate para implementar as invocações assíncronas de métodos.