[Problema] Sincronizando um Bloco de Código

Olá, amigos

Há algumas semanas durante os meus estudos para a OCJP, me deparei com este problema que está no capítulo de Threads do livro da Kathy Sierra:

In this exercise we will attempt to synchronize a block of code. Within that block of code we will get the lock on an object, so that other threads cannot modify it while the block of code is executing. We will be creating three threads that will all attempt to manipulate the same object. Each thread will output a single letter 100 times, and then increment that letter by one. The object we will be using is StringBuffer. We could synchronize on a String object, but strings cannot be modified once they are created, so we would not be able to increment the letter without generating a new String object. The final output should have 100 As, 100Bs, and 100 Cs all in unbroken lines.

Achei-o bem interessante e ao optar por implementá-lo pude aprender novos conceitos e entender como funciona a sincronização e bloqueio de objetos.
O problema pede para usar o conceito de sincronização, que em Java é feito com a palavra-chave synchronized. A autora quer que implementemos um método que imprima na saída 100 caracteres A’s, 100 B’s e 100 C’s, todos em sequência utilizando um único objeto. Não podemos usar um objeto String, pois elas são imutáveis, assim utiliza-se um objeto do tipo StringBuffer. A sincronização é feita bloqueando o acesso ao objeto e permitindo que apenas uma thread por vez obtenha este acesso.

Eis o código com alguns comentários:

public class MinhaThread implements Runnable {
	
	private StringBuffer letra;
	
	public MinhaThread(StringBuffer letra){
		this.letra = letra;
	}
	
	@Override
	public void run() {

		synchronized (letra) {
			//Imprime a Thread atual
			System.out.print("Thread #" + Thread.currentThread().getName() + ": " );
			
			for (int i = 1; i <= 100; i++) {
				System.out.print(letra);
			}
				//Incrementa a letra
				char aux = letra.charAt(0);
				aux++;
				letra.setCharAt(0, aux);
			
			System.out.println();	
		}
	}
	
	
}

Main:

public class Exercicio9_2 {
	public static void main(String[] args) {
		
		MinhaThread thread = new MinhaThread(new StringBuffer("A"));
		
		Thread t1 = new Thread(thread);
		Thread t2 = new Thread(thread);
		Thread t3 = new Thread(thread);
		
		t1.setName("1");
		t2.setName("2");
		t3.setName("3");
		
		t1.start();
		t2.start();
		t3.start();
		
	}
}

E a saída:

No método main instanciamos três objetos Thread, que serão responsáveis por criar três novas threads de execução. Como estas threads compartilham do mesmo objeto, se nós não sincronizarmos o acesso ao objeto StringBuffer, não teríamos garantias de qual thread iria ler e modificar este objeto. Assim a saída seria totalmente aleatória. Para ver o que isso causaria, remova o bloco synchronized e execute o método main novamente, você verá que a ordem com que a saída é impressa é diferente para cada execução.

Feita a sincronização, quando a primeira thread acessa o objeto, ela o bloqueia e não permite que outras threads tenham acesso a ele, até que ela finalize sua execução. Após finalizar o bloqueio é liberado até que a próxima thread o acesse e o bloqueie novamente.

Com a sincronização estamos seguros e temos a garantia que nossos objetos não terão seu valor modificado por outros acessos concorrentes.
Já imaginou como seria problemático se não houvesse bloqueio de objetos para operações de débito e créditos em contas correntes?

Este foi apenas um pequeno exemplo de como a sincronização funciona e é implementada em Java.
Espero que tenham gostado e entendido, mas caso tenham alguma dúvida e queiram fazer alguma pergunta fiquem à vontade. Terei o prazer em ajudá-lo caso eu saiba. Se eu não souber também será uma boa oportunidade para pesquisar e aprender um pouco mais.

Até a próxima! 😀

Anúncios

3 comentários em “[Problema] Sincronizando um Bloco de Código”

    1. Opa meu amigo,

      Apesar do bloqueio do objeto StringBuffer, não há nenhuma garantia de qual thread irá acessá-lo primeiro.
      Assim, poderiamos ter o acesso de qualquer Thread primeiro, segundo e terceiro. A única garantia que temos é que, ao acessar o objeto ele será bloqueado e não pode ser acessado por nenhuma outra thread até que esta termine sua execução.

      Poderíamos aumentar a prioridade das threads através do método setPriority, assim poderíamos simular execução numa ordem pré-definida.

      Espero que tenha entendido.

      Abração, parça e volte sempre!

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s