Sincronizacao duvida

ae pessoal o codigo abaixo tanto faz sincronizado como nao… ele imprime a mesma coisa nao entendi entao a diferença e o uso de bloquear usando essa sintaxe…

class SynTest extends Thread{
	public void Stuf(){
		System.out.println("non");
		//synchronized(this){
			for(int x=0;x<2;x++){
			System.out.println("num " + x +"  " + Thread.currentThread().getName());
			try{
			Thread.sleep(500);
			}catch(InterruptedException e){}
			}
		//}
	}
	public void run(){
		Stuf();
	}
	public static void main(String args[]){
		SynTest s = new SynTest();
		SynTest s2 = new SynTest();
			s.start();
			s2.start();
	}
}

:?:

Tente fazer um loop de 1000.

Você tem duas threads, usando dois objetos diferentes.

Nesse caso, não há diferença em usar ou não sincronização. A sincronização só é necessária quando duas threads usam o mesmo objeto.

e como resolvia esse problema ai? para que as duas thread possa referenciar ao mesmo objeto?
O que posso sincronizar?

  • metodos
  • variaveis
  • class
  • instancia da class

eu marcaria metodos e class ta certo?

Experimente rodar com esse código:

class SynTest extends Thread {
    private Writer writer;

    public SynTest(Writer w) {
        this.writer = w;
    }

    @Override
    public void run() {
        writer.doStuff();
    }
    
    public static void main(String[] args) {
        Writer w = new Writer();
        SynTest t1 = new SynTest(w);
        SynTest t2 = new SynTest(w);
        t1.start();
        t2.start();
    }
}

class Writer {
    public void doStuff() {
        System.out.println("non");
        synchronized (this) {
            for (int x = 0; x &lt 2; x++) {
                System.out.println("num " + x + "  "
                        + Thread.currentThread().getName());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                }
            }
        }
    }
}

somente uma thread foi executada…

non
num 0 Thread-0
num 1 Thread-0

resultado foi esse…
acabei de fazer esse para ver se entendo…

[code]
class Exe92 extends Thread{
public void run(){
synchronized(this){
for(int x=0;x<2;x++){
System.out.println(Thread.currentThread().getName());
System.out.println(“a”);
}

	}
}
Exe92(StringBuffer z){}
public static void main(String args[]){
	StringBuffer a = new StringBuffer("A");
	Exe92 e = new Exe92(a);
	Exe92 e2 = new Exe92(a);
	e.start();
	e2.start();
	
}

}

[/code]

ta certo?

Você pode sincronizar trechos de código. A “sincronização de método” é uma forma prática de sincronizar o trecho de código de um método inteiro, de uma só vez, usando como objeto de sincronização o this.

No código que eu fiz o resultado foi:

non
num 0 Thread-0
non
num 1 Thread-0
num 0 Thread-1
num 1 Thread-1

Note que, como o bloco é sincronizado, a thread 0 usa a impressão do número e valor completamente, antes que a thread 1 possa iniciar.

Apenas o non da thread 1 aparece “no meio” da thread 0, isso porque a impressão da palavra non não está num bloco sincronizado. Logo, ambas as threads puderam acessa-lo.

Retirando a sincronização obtive:
non
num 0 Thread-0
non
num 0 Thread-1
num 1 Thread-0
num 1 Thread-1

Veja como agora a execução ficou totalmente misturada.

infelizmente nao conseguir a saida… fiz ate um codigo mais simples mais nao entendi…


class Bloco extends Thread{
	public void run(){
		forca();
	}
	public void forca(){
		System.out.println("no");
		int y=10;
		synchronized(this){
			for(int x=0;x<2;x++){
				System.out.println(Thread.currentThread().getName() + " " + y);
				try{
					Thread.sleep(5000);
				}catch(InterruptedException e){}
				y++;
			}
		}
	}
	public static void main(String args[]){
		Bloco b = new Bloco();
		Bloco b1 = new Bloco();
		b.start();
		b1.start();
	}
}

quando tiro a sincronizacao o resultado eh o mesmo…

cara, faz um loop maior…

eh parece que agora entendi

class Bloco implements Runnable{
	public void run(){
		forca();
	}
	public void forca(){
		System.out.println("no");
		int y=10;
		synchronized(this){
			for(int x=0;x<2;x++){
				System.out.println(Thread.currentThread().getName() + " " + y);
				try{
					Thread.sleep(5000);
				}catch(InterruptedException e){}
				y++;
			}
		}
	}
	public static void main(String args[]){
		Bloco b = new Bloco();
		
		Thread t = new Thread(b);
		Thread t2 = new Thread(b);
		t.setName("dog");
		t2.setName("cat");
		t.start();
		t2.start();
	}
}

isso eh uma tremenda viajem… rpz… coisa de louco Thread…

Não adianta fazer um loop maior, embora certamente algumas impressões a mais ajudem.

Novamente, no caso da classe bloco, você criou 2 objetos distintos, e cada thread vai acessar seu próprio objeto. Não haverá diferença entre sincronizar ou não.

No caso da classe que eu fiz, o objeto Writer é compartilhado pelas duas threads.

[quote=ViniGodoy]No código que eu fiz o resultado foi:

non
num 0 Thread-0
non
num 1 Thread-0
num 0 Thread-1
num 1 Thread-1

Note que, como o bloco é sincronizado, a thread 0 usa a impressão do número e valor completamente, antes que a thread 1 possa iniciar.

Apenas o non da thread 1 aparece “no meio” da thread 0, isso porque a impressão da palavra non não está num bloco sincronizado. Logo, ambas as threads puderam acessa-lo.

Retirando a sincronização obtive:
non
num 0 Thread-0
non
num 0 Thread-1
num 1 Thread-0
num 1 Thread-1

Veja como agora a execução ficou totalmente misturada.[/quote]
po vinny saquei valeu… rpz… isso eh uma noia viu? ave-maria… agora o codigo abaixo eh valido quando tenho extends Thread? posso dizer que ta acessando o mesmo objeto?

Exe92 e = new Exe92(a);
		Exe92 e2 = new Exe92(a);
		e.start();
		e2.start();

Sua execução pode ser descrita assim:

  1. A thread t entra no método forca;
  2. A thread t1 entra no método forca;
  3. A thread t requisita a sincronização na chave this (t). E consegue, pois a chave t está livre.
  4. A thread t1 requisita a sincronização na chave this (t1). E consegue, pois a chave t1 está livre (são objetos diferentes);
  5. A thread t executa o primeiro loop do for;
  6. A thread t1 executa o primeiro loop do for;
  7. A thread t executa o segundo loop do for;
  8. A thread t1 executa o segundo loop do for;
  9. A thread t1 executa o terceiro loop do for;
  10. A thread t executa o terceiro loop do for;
  11. A thread t finaliza e libera a chave t;
  12. A thread t1 finaliza e libera a chave t1;

Note que, como você tem dois objetos, também tem 2 chaves de sincronização. Por isso, não interessa rodar ou não com código sincronizado.

No caso do método Write e da minha classe, acontece o seguinte:

  1. A thread t1 inicia;
  2. A thread t2 inicia;
  3. A thread t1 imprime non;
  4. A thread t1 requisita a sincronização do this (no caso, o Writer w);
  5. A thread t2 imprime non;
  6. A thread t2 requisita a sincronização do this (no caso, o Writer w), mas não consegue, pois está em uso por t1. Ela então dorme e espera;
  7. A thread t1 executa a primeiro loop do for;
  8. A thread t1 executa a segundo loop do for;
  9. A thread t1 executa a terceiro loop do for;
  10. A thread t1 finaliza a execução liberando a chave w;
  11. A thread t2 acorda, pega a chave this (w) e executa a primeiro loop do for;
  12. A thread t2 executa a segundo loop do for;
  13. A thread t2 executa a terceiro loop do for;
  14. A thread t2 finaliza e libera a chave w;

Se ambas as threads tiverem apontando uma referência apontando para o mesmo objeto, sim.

No caso, das minhas threads:
t1.writer == t2.writer

o que eu posso sincronizar de verdade: metodos e variaveis de instancia?

Trechos de código apenas… apenas trechos de código…

Portanto, o modificador sincronized poderá ser usado para um método, para sincronizar todo o trecho de código no interior daquele método, mas não para uma variável.

O synchronized (variavel) {…} não está sincronizando a variável em si, mas o código que vem logo abaixo, entre chaves. É uma das formas de se sincronizar apenas uma parte de um método.

A variável naquele caso só indica o objeto que está sendo usado para o controle da sincronização. Quando uma Thread entra nesse trecho de código sincronizado ela “captura” esse objeto. Outras threads não poderão fazer o mesmo e terão que esperar.

Por isso no seu programa a sincronização não surtiu efeito. Como você tinha 2 objetos, cada thread pode capturar o seu próprio “this” e, portanto, tiveram acesso ao código sincronizado.