Prof. Silvana Rossetto 9 de julho de DCC/IM/UFRJ

Documentos relacionados
Semáforos. Gerenciamento de Recursos I

Threads em Java. Java Threads. Java Componentes: JVM JVM:

Sistemas Operacionais: Sincronização entre processos

Programação Concorrente com Thread Java. Luiz Affonso Guedes Sistemas Distribuidos

Sistemas Operacionais. Prof. André Y. Kusumoto

Threads. Linguagem Java. Adenilso da Silva Simão 17/05/05

MC504 Sistemas Operacionais MC514 Sistemas Operacionais: Teoria e

Problemas Típicos de Sincronização

Programação concorrente em Java

Semáforos. Gerenciamento de Recursos I

Sincronização. Cooperação entre Processos

Cooperação entre Processos

Só podem ser executados por uma Thread que detenha o lock do objecto

LabSO Gerência de Processos. Retrospectiva da aula passada... Na aula passada... Na aula passada...

Sistemas Operacionais. Prof. André Y. Kusumoto

Fundamentos de Sistemas Operacionais

Problema dos Leitores/Escritores

Sistemas Operacionais

Sincronização. Cooperação entre Processos

Métodos Sincronizados

Threads. O que é uma Thread? Paralelismo

Mecanismos de Sincronização com Variáveis Compartilhadas

Sistemas Distribuídos Aula 7

Sincronização de Threads

O PROBLEMA DOS LEITORES E ESCRITORES LABORATORIO 1

Programação Concorrente em Java

UNIVERSIDADE FEDERAL RURAL DE PERNAMBUCO Bacharelado em Sistemas de Informação. Processamento Paralelo Threads. Aluno: Wagner Palacio

Sincronização. Objectivos da aula de hoje

OO Engenharia Eletrônica

UNIVERSIDADE FEDERAL FLUMINENSE INSTITUTO DE COMPUTAÇÃO DEPARTAMENTO DE CIÊNCIA DA COMPUTAÇÃO

Monitores. Programação Concorrente September 11, 2012

Carlos Eduardo Batista Centro de Informática - UFPB

Tratamento de Exceções, Multithreads e arquivos (em Java) Programação Orientada a Objetos

Sistemas Operacionais. Sincronização: Semáforos Problema dos Leitores/Escritores

Laboratório 3 Comandos de repetição while, do-while e for

Universidade Federal do Pará Instituto de Ciências Exatas e Naturais Faculdade de Computação

Sistemas Operacionais II

DEPARTAMENTO DE CIÊNCIA DA COMPUTAÇÃO SISTEMAS OPERACIONAIS I SEM/12 PROVA I. Tempo de Prova: 100 minutos / Escore Máximo: 300 pontos

Sistemas Operacionais

Variáveis primitivas e Controle de fluxo

Utilizando Threads em Java

Sistemas Operacionais

Sistemas Operacionais

Segundo trabalho prático de implementação Sistema de reserva de assentos

Fundamentos de Sistemas Operacionais

Aula 7. Problemas Clássicos de Sincronização. 1.1 O Jantar dos Filósofos. 1.2 Leitores e Escritores. 1.3 O Barbeiro Dorminhoco

Sincronização. Cooperação entre Processos

Roteiro. BC1518-Sistemas Operacionais. Prof. Marcelo Z. do Nascimento Semáforos

Introdução à Programação. Estruturas de Repetição

Concorrência. Condições de Corrida. 5a. Tentativa. Dificuldades: Sincronização de Processos (2) Aula 11 Profa. Patrícia Dockhorn Costa

Múltiplas Linhas de Execução Java (Threads)

Sistemas Distribuídos Aula 5

[Magee 1999] Concurrency State Models and Java Programs, Jeff Magee, Jeff Kramer, John Wiley 1999.

Métodos Sincronizados

Comunicação entre processos

Unidade III Gerência de Processos

Monitores. Paulo Sérgio Almeida. Grupo de Sistemas Distribuídos Departamento de Informática Universidade do Minho

Sincronização e Comunicação entre Processos

Execução Concorrente

PUC-SP Depto. de Ciência da Computação

(Aula 17) Threads em Java

Introdução a Programação Concorrente. Aula 02. Prof. André Luis Meneses Silva

Monitores. Setembro de Monitores

Sistemas Operativos: Concorrência (Parte 2)

Métodos Computacionais. Comandos Condicionais e de Repetição em C

SSC0640 Sistemas Operacionais I

Fundamentos de Programaçã. ção Concorrente

Teste de Sistemas de Operação 30 de Maio de 2009

Computação Paralela. Especificação de Concorrência/Paralelismo. João Luís Ferreira Sobral Departamento do Informática Universidade do Minho

1º teste Grupo III

Programação Orientada a Objetos. Concorrência

Sincronização. Problema da Exclusão Mútua

Linguagem C (repetição)

Linguagem de Programação

Introdução à Programação. Estruturas de Repetição

Sistemas Operacionais

Sistemas Operacionais II

Unidade 3. Controle de Concorrência. Primitivas de Programação Concorrente Clássica

Tipos de dados e comandos POO

[Magee 1999] Concurrency State Models and Java Programs, Jeff Magee, Jeff Kramer, John Wiley 1999.

Universidade de Mogi das Cruzes Implementação Orientada a Objetos - Profª. Danielle Martin. Guia da Sintaxe do Java

UNIVERSIDADE ESTADUAL DE PONTA GROSSA SETOR DE CIÊNCIAS AGRÁRIAS E DE TECNOLOGIA DEPARTAMENTO DE INFORMÁTICA

Bacharelado em Ciência e Tecnologia Processamento da Informação. Equivalência Portugol Java. Linguagem Java

C Comandos de Controle

UNIP - Ciência da Computação e Sistemas de Informação. Estrutura de Dados. AULA 5 Pilhas

BC1518-Sistemas Operacionais. Prof. Marcelo Z. do Nascimento

Sincronização e Comunicação entre Processos. Sincronização e Comunicação Volnys Bernal 1. Agenda

1 a Questão Unidade I e II (45 pontos)

Trincos Lógicos: Implementações. Trincos lógicos: Propriedades

Waldemar Celes e Roberto Ierusalimschy. 29 de Fevereiro de 2012

Linguagem Java - Introdução

Prova Final de Linguagens de Programação - DCC024B -

Arquitetura de Sistemas Operativos

Introdução a JAVA. Variáveis, tipos, expressões, comandos e blocos

Redes de Computadores. INF201 - Fundamentos de Sistemas Operacionais - 2º Período

Gabriel de Oliveira Ramos Roland Teodorowitsch - Orientador

Sintaxe Básica de Java Parte 2

Sistemas Operacionais

Transcrição:

Computação Concorrente (MAB117) Gabarito Segunda Prova Prof. Silvana Rossetto 9 de julho de 2015 1 DCC/IM/UFRJ Questão 1 (2,5 pts) O código Java abaixo implementa uma solução para o problema do barbeiro dorminhoco. O barbeiro só pode atender a um cliente de cada vez. Há 5 cadeiras de espera e os clientes são atendidos por ordem de chegada. Em uma aplicação foram implementadas threads para os clientes e para o barbeiro. A thread dos clientes chama repetidamente o método EsperaBarbeiro() até que ele retorne true. A thread do barbeiro chama os métodos EsperaCliente e TerminaCliente N vezes (N=n o de threads cliente). (a) Se executarmos essa aplicação com 10 threads cliente e uma thread barbeiro ela funcionará corretamente? (b) A chamada notifyall() na linha 14 pode ser substituída por uma chamada notify()? (c) A linha 24 pode ser substituída pela linha if(this.esperando > 0) notifyall(); sem alterar a corretude da solução? Justifique suas respostas. Respostas sem justificativa não serão consideradas. 1: class Cadeira { //...declaração de variaveis 2: Cadeira() { this.esperando = 0; //numero de clientes esperando (no maximo 5) 3: this.ocupado = 0; //estado do barbeiro (0: livre; 1: ocupado) 4: this.proximocliente = 0; //senha do cliente no inicio da fila de espera 5: this.ultimocliente = 0; //proxima senha do cliente que entrar na fila 6: 7: public synchronized boolean EsperaBarbeiro () { 8: if(this.esperando == 5) return false; 9: int minhasenha = this.ultimocliente; 10: this.ultimocliente++; 11: this.esperando++; 12: while(this.proximocliente!= minhasenha) wait(); 13: this.ocupado = 1; 14: notifyall(); 15: return true; 16: 17: public synchronized void EsperaCliente () { 18: while((this.esperando == 0) (this.ocupado == 0)) wait(); 19: this.esperando--; 20: 21: public synchronized void TerminaCliente () { 22: this.ocupado = 0; 23: this.proximocliente++; 24: notifyall(); 25: 26: Resp.: (a) Vamos considerar todas as possíveis combinações de execução das threads. Se o barbeiro começar primeiro, ele chamará o método EsperaCliente(), como o valor do atributo esperando será 0, o barbeiro irá se bloquear. Quando o primeiro cliente chegar, o atributo proximocliente será igual ao atributo minhasenha, então ele alterará o atributo ocupado para 1, desbloqueará o barbeiro e estará pronto para ser atendido. O barbeiro irá verificar que as duas condições do while avaliam falso, decrementará o número de clientes esperando e estará pronto para atender o cliente. Se chegarem em seguida todos os outros clientes, 5 deles ficarão bloqueados porque chamarão a função wait(), uma vez que o atributo proximocliente não será igual

ao atributo minhasenha de cada um deles. Os demais clientes que tentarem entrar, sairão pela linha 8. Quando o barbeiro terminar com o primeiro cliente, ele chamará o método TerminaCliente() onde alterará o atributo ocupado para 0 (sinalizando que está livre) e incrementará o atributo proximocliente, possibilitando que apenas o segundo cliente a entrar na barbearia consiga deixar o while da linha 12. Em seguida ele chama o método notifyall() para desbloquear todos os clientes esperando. Se logo em seguida o barbeiro conseguir executar o método EsperaCliente() (antes de qualquer cliente voltar), o barbeiro irá se bloquear na linha 18 (pois o atributo ocupado é igual a 0). Quando o segundo cliente conseguir voltar a executar ele alterará novamente o atributo ocupado para 1 e através da chamada a notifyall() irá acordar o barbeiro que sairá do while da linha 18. Por outro lado, se antes do barbeiro executar o método EsperaCliente(), o segundo cliente conseguir executar após ser desbloquado, ele marcará ocupado com o valor 1. Então quando o barbeiro executar EsperaCliente(), o while da linha 18 avaliará falso e ele seguirá executando a linha 19. A aplicação então prosseguirá até que todos os clientes sejam atendidos. Se no início algum (ou alguns) clientes chegarem antes do barbeiro, o primeiro cliente alterará o atributo ocupado para 1 e estará pronto para ser atendido. O demais clientes ficarão bloqueados na linha 12. Quando o barbeiro entrar, o while da linha 18 avaliará falso e ele prosseguirá para atender o primeiro cliente. Dessa forma, podemos concluir que a aplicação funcionará corretamente independente do número de threads cliente. (b) Não, a chamada notifyall() na linha 14 não pode ser substituída por uma chamada notify() porque sua finalidade é desbloquear o barbeiro e como é possível ter clientes bloqueados na mesma variável de condição, não garantiríamos que o barbeiro seria desbloqueado sempre. (c) Sim, a linha 24 pode ser substituída pela linha if(this.esperando > 0) notifyall(); sem alterar a corretude da solução pois o barbeiro só precisa desbloquear os clientes se houver clientes esperando. Questão 2 (2,5 pts) Usando semáforos em C, implemente a função void barreira(int numthreads) para oferecer uma solução de sincronização por barreira (ou sincronização coletiva). O argumento numthreads informa o número de threads que deverão chamar a função barreira a cada iteração, ou seja, sempre que uma thread chamar essa função ela deverá ficar bloqueada até que todas as threads (numthreads) chamem a mesma função. sem_t mutex, cond; int bloqueadas=0; //inicializacao na main... sem_init(&mutex,0,1); //semaforo para exclusao mutua sem_init(&cond,0,0); //semaforo para bloqueio incondicional void barreira(int numthreads) { sem_wait(&mutex); //esclusão mútua bloqueadas++; //indica que mais uma thread chegou if (bloqueadas < numthreads) { //verifica se é a última thread sem_post(&mutex); //nao é a ultima thread, libera a exclusao mutua sem_wait(&cond); //se bloqueia (para aguardar todas as threads) bloqueadas--; //depois de ser desbloqueada, decrementa o numero de threads //dessa iteracao if (bloqueadas==0) sem_post(&mutex); //se for a ultima thread a sair, //libera a exclusao mutua

else sem_post(&cond); //se nao for a ultima thread a sair, desbloqueia outra thread else { //se for a ultima thread a chegar na barreira, desbloqueia uma thread //e nao libera a exclusao mutua para garantir que todas as threads sairao //da barreira antes das threads conseguirem iniciar a proxima barreira bloqueadas--; sem_post(&cond); Questão 3 (2,5 pts) O código abaixo implementa uma solução para o problema dos leitores e escritores, com prioridade para escritores (sempre que um escritor está esperando para escrever, novos leitores não podem começar a ler). (a) Esse código pode levar a aplicação a uma situação de deadlock? (b) Esse código garante a prioridade para escritores? Justifique suas respostas. Respostas sem justificativa não serão consideradas. Resp.: (a) Não, esse código não levará a aplicação a uma situação de deadlock. Uma situação de deadlock ocorre quando uma ou mais threads da aplicação ficam bloqueadas e as threads que poderiam desbloqueá-las também estão bloqueadas ou finalizadas. Todos os semáforos são inicializados com um sinal. O semáforo usado para exclusão mútua ( em ) é sempre decrementado e incrementado pelas threads. Na primeira parte do código dos leitores, as threads incrementam o semáforo de exclusão mútua antes de

se bloquarem no semáforo de prioridade ( prior ) nas linhas 5 e 6. Sempre que uma thread leitora é desbloqueada do semáforo de prioridade ela incrementa esse semáforo garantindo assim que todas as threads leitoras que estão aguardando operações de escrita sejam em algum momento desbloqueadas. Apenas a primeira thread leitora (em cada bloco de execução das threads leitoras) decrementa o semáforo de escrita ( escrita ), isso garante que quando o escritor terminar de escrever, o incremento feito por ele no semáforo de escrita será suficiente para liberar todas as threads leitoras em espera. Da mesma forma, quando todas as threads leitoras terminam um bloco de execução, apenas um incremento é feito no semáforo de escrita permitindo que threads escritoras executem ou que um novo bloco de leitores se inicie. Do lado dos escritores, o decremento no semáforo de prioridade nunca causará bloqueio na thread pois apenas a primeira thread escritora em espera fará isso e o semáforo necessariamente terá um sinal. Posteriomente, como o semáforo de prioridade só é incrementado quando a última thread escritora em espera conclui sua execução, ele voltará a ter um sinal. Sendo assim, podemos concluir que não há possibilidade de bloqueios indefinidos das threads dessa aplicação. (b) Sim, esse código garante a prioridade para escritores porque sempre que um escritor quer escrever ele deixa sinalizado na variável num escresp que há um escritor esperando. Se ele for o primeiro escritor na fila, ele também consumirá o sinal do semáforo prior e apenas quando o último escritor da fila conseguir escrever esse semáforo será incrementado. Os leitores, por sua vez, sempre verificam o valor da variável num escresp antes de começarem a ler. Quando há escritores esperando, os leitores necessariamente se bloquearão na linha 6 (código dos leitores) pois o semáforo prior não terá sinais sobrando. Além disso não é possível um leitor chegar até a linha 12 do código dos leitores se já houver escritor esperando ou escrevendo. Questão 4 (2.5 pts) Para dançar a quadrilha de São João é preciso formar um par (um homem e uma mulher). Considere uma aplicação com threads homem e mulher. Escreva uma classe Java (monitor) que ofereça os métodos entramulher() e entrahomem() os quais deverão ser chamados pelas threads mulher e homem, respectivamente, antes de entrarem na quadrilha. O métodos devem garantir que cada thread bloqueie até formar um par e que as threads deixem o monitor sempre em pares. class Pares { private int m, h, formandoparm, formandoparh; Pares() { this.m = 0; //numero de mulheres esperando um par this.h = 0; //numero de homens esperando um par this.formandoparm = 0; //se==1, uma mulher já foi selecionada para o proximo par this.formandoparh = 0; //se==1, um homem já foi selecionado para o proximo par // Barreira para mulheres public synchronized void entramulher (int id) { try { this.m++; while ((this.h == 0) (this.formandoparm == 1)) { wait(); //bloqueia pela condicao logica da aplicacao this.formandoparm = 1; //uma mulher foi selecionada para formar um par

if(this.formandoparh == 0) { notifyall(); //desbloqueia os homens esperando par else { this.m--; this.h--; //um par foi formado this.formandoparm = 0; this.formandoparh = 0; //termina a formacao do par catch (InterruptedException e) { // Barreira para homens public synchronized void entrahomem (int id) { try { this.h++; while ((this.m == 0) (this.formandoparh == 1)) { wait(); //bloqueia pela condicao logica da aplicacao this.formandoparh = 1; //um homem foi selecionado para formar um par if(this.formandoparm == 0) { notifyall(); //desbloqueia as mulheres esperando par else { this.m--; this.h--; //um par foi formado this.formandoparm = 0; this.formandoparh = 0; //termina a formacao do par catch (InterruptedException e) {