Duvida codigo com threads

9 respostas
N

Pessoal, estou começando o estudo sobre threads na facul, estamos implementando junto com o professor esse programinha que utiliza duas threads para a escrita e leitura dos valores que estão no vetor.

Bom minha duvida é uma questão que o professor levantou na ultima aula:

Por que o código teria problemas caso o WHILE da da linha 27 do método gravar() da classe BufferCircular fosse trocado por um IF, e a mesma pergunta pra Troca do WHILE da linha
53 do método ler().

Sei a diferença de WHILE e IF, mas nao soube explicar o porque do prejuízo caso houvesse a troca!

Alguém tem alguma ideia?

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class CircularBuffer implements IBuffer{

	private int valores[];
	private int r;
	private int w;
	private int quantidade;
	
	private Lock bloqueio = new ReentrantLock();
	private Condition podeGravar = bloqueio.newCondition();
	private Condition podeLer = bloqueio.newCondition();
	
	public CircularBuffer(int tamanho){
		valores = new int[tamanho];
		w = 0;
		r = 0;
		quantidade = 0;
	}
	
	@Override
	public void gravar(int valor) {
		bloqueio.lock();
		
		while(quantidade == valores.length){
			try {
				System.out.println("Produtor esperando....");
				podeGravar.await();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		System.out.println("Gravando: " + valor);
		this.valores[w] = valor;
		
		w = (w + 1) % valores.length;
		quantidade++;
		
		podeLer.signal();
		
		bloqueio.unlock();
	}

	@Override
	public int ler() {
		int auxiliar = 0;
		
		bloqueio.lock();
		
		while(quantidade == 0){
			try {
				System.out.println("Consumidor esperando....");
				podeLer.await();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		System.out.println("Lendo: " + valores[r]);
		auxiliar = valores[r];
		
		r = (r + 1) % valores.length;
		quantidade--;
		
		podeGravar.signal();
		
		bloqueio.unlock();
		
		return auxiliar;
	}
	
}

A classe que controla a escrita:

import java.util.Random;

public class Produtor implements Runnable{

	private IBuffer buffer;
	
	public Produtor(IBuffer buffer) {
		this.buffer = buffer;
	}
	
	@Override
	public void run() {
		int somatorio = 0;
		for(int i = 1; i <=1000000; i++){
			buffer.gravar(i);
			somatorio += i;
			//esperaCronometrada();
		}
		System.out.println("Produtor escreveu: " + somatorio);
	}

	private void esperaCronometrada() {
		try {
			Random r = new Random();
			Thread.sleep(r.nextInt(100));
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

Classe que controla a leitura:

public class Consumidor implements Runnable{

	private IBuffer buffer;
	
	public Consumidor(IBuffer buffer) {
		this.buffer = buffer;
	}
	
	@Override
	public void run() {
		int somatorio = 0;
		for(int i = 1; i <=1000000; i++){
			somatorio += buffer.ler();
			//esperaCronometrada();
		}
		System.out.println("Consumidor leu: " + somatorio);
	}

	private void esperaCronometrada() {
		try {
			Random r = new Random();
			Thread.sleep(r.nextInt(100));
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

Classe do main:

package br.upis.tu382;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Principal {
	public static void main(String[] args) {
		ExecutorService pool;
		pool = Executors.newFixedThreadPool(2);
		
		IBuffer buffer = new CircularBuffer(5);
		
		Runnable produtor = new Produtor(buffer);
		Runnable consumidor = new Consumidor(buffer);
		
		pool.execute(produtor);
		pool.execute(consumidor);
		
		pool.shutdown();
	}
}

9 Respostas

Rodrigo_Sasaki

É só pensar na lógica, se fosse um teste if ele somente seria executado uma vez.

agora como é um while enquanto aquela condição não for satisfeita, ou seja, enquanto a outra thread não terminar o que tiver que fazer, você fica preso naquele bloco.

se não houver um while você pode ficar com dados incompletos no meio da exeucção.

N

Eu pensei nisso, mas como no teste do código com o if nenhum dado foi perdido, pensei que a resposta estaria incompleta!

Fellipex

Bom não entendi muito bem o que você quis dizer, pois você disse que sabia a diferença entre o WHILE e o IF, no caso se a condição fosse atendida no IF ele entraria uma vez , executaria o escopo dentro dele
assim que terminar continua com o restante do método, já no WHILE, enquanto a condição for verdadeira ele permanecerá executando aquele escopo até que em algum momento a condição passe a ser false, valeu =D

N

Valeu gente,

Na verdade eu queria saber qual o prejuizo caso fosse trocado o while pelo if… Será que não seria uma questão de mais demora no processamento?

Rodrigo_Sasaki

Então, não quer dizer que não vá funcionar nunca.

quer dizer que você não pode garantir que funcione, pode ser que em algum caso, não dê tempo e algum dado seja perdido, entendeu? com o while você garante que isso não vai acontecer.

N

Ah sim, entendi!

Então ta respondida a minha pergunta!

Obrigada diogaoneves e Fellipex!

leandropena

Achei um pouco confuso os códigos, acho que poderiam ser mais simples.
Pelo que bem entendi, se voce trocar o while pelo if ele fará o teste apenas uma vez e poderá ter concorrencia para execução dos métodos de leitura/escrita, ou seja, pode ser que os dois métodos sejam chamados no mesmo instante por threads diferentes, fazendo com que os valores dos atributos envolvidos não sejam garantidos ao final da execução das threads.

rogeriopaguilar

No livro effective java segunda edição - capítulo 10 ele explica os problemas que podem ocorrer utilizando o if ao invés do while. Na versão em inglês do livro são as páginas 276 e 277.

fidelis_felipe

mas qual é diferença mesmo? No livro diz que o segmento pode entrar em um estado nao deterministico por se tratar de inanição.

Mas qual a diferença da alteração ser feita no leitor. E qual a diferença no gravador?
Acho que como é leitura e gravação são problemas distintos. Talvez a concorrencia tenha haver mas seria apenas a inanição?

Criado 19 de setembro de 2012
Ultima resposta 20 de set. de 2012
Respostas 9
Participantes 6