Métodos sincronizados

3 respostas
S
Olá pessoal, estou com uma dúvida em métodos sincronizados. Codigo do livro SCJP que imprime 1000 As, 1000Bs e 1000Cs:
public class MyThread extends Thread {
	StringBuffer letter; 
	
	public MyThread(StringBuffer s){
		this.letter = s; 
	}
	
	public void run(){
		synchronized (letter) {
			
			for(int i=0; i<1000; i++){
				System.out.println(Thread.currentThread().getName() + ": " + letter + " index: " + i);
			}

			char c = letter.charAt(0);
			++c; 
			letter.setCharAt(0, c);
		}
	}

	public static void main(String[] args) {
		StringBuffer l = new StringBuffer("a");
		
		MyThread t1 = new MyThread(l);
		MyThread t2 = new MyThread(l);
		MyThread t3 = new MyThread(l);
		
		t1.setName("Thread1");
		t2.setName("Thread2");
		t3.setName("Thread3");
		
		t1.start();
		t2.start();
		t3.start();
	}
}
Porquê um objeto StringBuffer foi usado para bloquear o trecho?:
public void run(){
		synchronized (letter) {
			
			for(int i=0; i<1000; i++){
				System.out.println(Thread.currentThread().getName() + ": " + letter + " index: " + i);
			}

			char c = letter.charAt(0);
			++c; 
			letter.setCharAt(0, c);
		}
	}
O bloqueio não poderia ter sido na própria instância this?
public void run(){
		synchronized (this) {
			
			for(int i=0; i<1000; i++){
				System.out.println(Thread.currentThread().getName() + ": " + letter + " index: " + i);
			}

			char c = letter.charAt(0);
			++c; 
			letter.setCharAt(0, c);
		}
	}

Obrigado!

3 Respostas

P

Por que se você coloca-se o this, pra cada novo objeto um novo bloquei seria criado, assim cada instancia tem seu próprio método que acessa o mesmo StringBuffer, se você reparar no código, o mesmo objeto StringBuffer esta sendo passado como paramentro para o construtor, dessa fora so existe um bloqueio, então ele so pode ser acessado por uma instancia de MyThread por vez.
Não sei se foi muito claro.
Flw

J

Quando você usa o synchronized(this), é o mesmo que colocar o synchronized no metodo. O lock é feito para o objeto inteiro, o que pode gerar locks desnecessarios em certas situações, como por exemplo:

public class Teste {
   private StringBuffer buf1;
   private StringBuffer buf2;

   public void addStr1(String str){
         synchronized(this) {
             buf1.append(str);
         }
   }

   public void addStr2(String str){
      synchronized(this){
         buf2.append(str);
      }
   }
}
public class Teste {
   private StringBuffer buf1;
   private StringBuffer buf2;

   public void addStr1(String str){
         synchronized(buf1) {
             buf1.append(str);
         }
   }

   public void addStr2(String str){
      synchronized(buf2){
         buf2.append(str);
      }
   }
}

A diferença entre o exemplo 1 e 2 é que no exemplo 1 ao chamar um metodo será criado um lock para todo o objeto Teste, inclusive a chamada para o outro metodo estará bloqueada.

No exemplo 2 os objetos dos dois blocos sincronizados são diferentes, portanto eles podem ser executados ao mesmo tempo por threads diferentes..

S

Agora sim!
Valew :lol:

Criado 7 de março de 2008
Ultima resposta 9 de mar. de 2008
Respostas 3
Participantes 3