Sincronizando threads

8 respostas
H
Galera não estou conseguindo entender muito bem, quando se diz que obtem o bloqueio do objeto, do objeto quer dizer oque ?? de onde??? Da classe ThreadA!!!! Olha esse exemplo:
01 public class ThreadA {
02  	public static void main(String[] args) {
03  		ThreadB b = new ThreadB();
04 		b.start();
05  		synchronized (b) {
06  			try {
07  				System.out.println("Waiting for b to complete...");
08  				b.wait();
09  			}catch (Exception e) { }
10  			System.out.println("Total is: " + b.total);
11  		}
12  	}
13 }
 
14 public class ThreadB extends Thread {
15  	int total;
16  	public void run() {
17  		synchronized (this) {
18  			for(int i=0; i < 1000; i++) {
19  				total += i;
20  				System.out.println(total);
21  			}
22  			notify();
23  		}
24  	}
25 }
Foi criado uma instancia de ThreadB chamada "b", depois foi chamado o método start(), nisso a thread "main" continuo a sua execução e a referência "b" obteve o bloqueio, e chamou o método wait() fazendo com que a thread "main" entre para o extado executavel na lista de espera de "b" e fique aguardando uma notificação de "b", que esta calculando um total. Depois que for finalizado o laço de repetição "b" notifica a thread main que esta na sua lista de espera, então a thread main entra no bloco sincronizado da classe ThreadA, printa "Waiting for b to complete...", deposi printa "Total is: " + b.total.

Seria isso... me confundo na hora da sincronização...
O bloco sincronizado de que classe é executado primeiro?????
Por exemplo, ta certo afirmar que b obteve o bloqueio e main entrou na sua lista de espera.... Depois quando b notificou, apartir de que lugar a thread main voltou a executar.... Do inicio do bloco sincronizado???????
Depois de wait()????
Dúvidas, dúvidas e mais dúvidas...

8 Respostas

S

Não se pode saber qual o bloco de que classe é executado primeiro esse é o ponto em usar Threads!!!

O que acontece é que se o o bloco do main for executado primeiro quando chegar a b.wait e vai parar e esperar que b o notifique. Se ele corre depois, quando chegar a b.wait ele já continua pq b não existe mais.

So uam dica. use notifyAll em vez de notify mesmo que supostamente so exista uma thread esperando.

Recomendo que use os novos objetos de java.concurrent sobretudo BlockingQueue e padrão de alto nivel como produtor-consumidor, em vez de se preocupar com Threads. Threads é legal mas é complicado. Tem um livro da O’Riley chamado Threads que recomendo bastante.

H

Então no método “main”, o bloco sincronizado é utilizado pela thread b, certo!!!
Que quer dizer que “b” obteve o bloqueio, mas bloqueio de que???
Da execução da classe???

Nesse ponto a thread “b” já esta em execução e quando ela finaliza, notifica a thread “main” que estão no seu poll de espera.

S

O bloco sincronizado não é usado pela Thread B e sim pela thread principal. A thread principal não é o objecto nem a classe ThreadA mas sim a thread que a JVM criou antes de chamar o main.

synchronized (b) não significa “sincroniza com b” ou “bloqueia b” significa “usa b para sincronizar a thread corrente” o fato de b ser um objeto Thread é irrelevante aqui. Poderia ser qualquer classe que herde de Object.

O bloco synchronized (this) dentro da Thread é irrelevante pq essa thread não cria outras threads com quem se sincronizar.

Para mandar correr uma thread e esperar que ela termine o comando certo é join e não wait. join é tipo especial de wait que espera que a thread termine em vez de esperar uma notificação.

Num ambiente multi-thread não ha bloqueio. Essa é a graça de usar várias Threads. O máximo que se pode fazer é fazer uma thread esperar por outra, mas é só.

H

Então a thread “main” utilizou o objeto “b” para bloquear a execução da thread corrente, que neste caso é a “main”.
Pelo fato de utilizar “b” para bloquear a thread em execução(main), só “b” poderá notificar a thread “main”!!!
Se a Thread “b” que esta sendo executada, não nofiticar sua(s) thread(s), “main” nunca mais sairá do estado executável.

Seria isso?

S

“heidermatos”:
Então a thread “main” utilizou o objeto “b” para bloquear a execução da thread corrente, que neste caso é a “main”.

sim

Só b pode ser usado para notificar a thread main. É diferente de so b poder notificar. Qualquer thread the tenha acesso a b pode usar b para notificar a thread main.


Se a Thread “b” que esta sendo executada, não nofiticar sua(s) thread(s), “main” nunca mais sairá do estado executável.

Seria isso?

Não é bem isso. Se b nunca for notificado, main nunca será liberanda. Mas não existe o conceito de “as suas threads”

H

Oque eu quiz dizer com “Suas Threads”, é que uma thread pode ter muitas outras em sua lista de espera.
Não neste exemplo, entendeu.
Por que “b” só pode possui uma em sua lista, que neste exemplo poderia ser a “main”.

Muito obrigado pelas explicações sergio.

S

“heidermatos”:
Oque eu quiz dizer com “Suas Threads”, é que uma thread pode ter muitas outras em sua lista de espera.
Não neste exemplo, entendeu.
Por que “b” só pode possui uma em sua lista, que neste exemplo poderia ser a “main”.

Muito obrigado pelas explicações sergio.

Na realidade é ao contrário. Qualquer objeto tem o método wait() portanto qualquer objeto pode ter uma coleção de listas esperando. É o objeto sincronizado , o que fica dentro de “sinchronize(x)” que mantém a lista de espera. A thread em si mesmo não mantém nenhuma informação sobre nenhuma outra thread. (exatamente por isso é preciso um objeto para fazer o sincronismos)

H

Isto eu sei, pelo fato de todas as classes extenderem de Object implicitamente.
No mais, muito obrigado!!!

Criado 2 de fevereiro de 2007
Ultima resposta 5 de fev. de 2007
Respostas 8
Participantes 2