thread  XML
Índice dos Fóruns » Java Básico
Autor Mensagem
fabioEM
GUJ Master
[Avatar]
Membro desde: 13/09/2007 13:34:23
Mensagens: 1041
Offline

Por gentileza alguem poderia me explicar pq o resultado desse codigo é sempre ou wallace wallace,ou goiac goic ou 1-1 ou 2-2
ou seja segue sempre uma repeticao?

"Um pouco de ciência nos afasta de Deus. Muito, nos aproxima." (Louis Pasteur)
Conheçam Sócrates: http://www.youtube.com/watch?v=SlJSF-V6yBA
Conheçam a obra social Célio Lemos: http://www.oscl.org.br/site/
Conheçam o Projeto: http://www.youtube.com/watch?v=9-k818tfG6M&feature=youtu.be
Sun Certified Java Programmer 1.5
thundercas
JavaEvangelist
[Avatar]

Membro desde: 15/09/2007 11:04:51
Mensagens: 429
Localização: São Paulo - SP
Offline

Dentro do método run() você chama duas vezes o método me(). Por isso o mesmo nome é exibido duas vezes...

No entanto, não é exibido 1-1 ou 2-2, veja abaixo como ficou aqui:


wallace - 1
wallace - 2
gloiac - 1
gloiac - 2

This message was edited 1 time. Last update was at 04/01/2008 21:35:07


Cassiano Colombo de Oliveira Gil
Analista Programador Junior
São Paulo - SP
E-mail: cassi_ano@hotmail.com
Twiter: http://twitter.com/thundercas
[Email] [MSN]
rdomartins
Entusiasta Java
[Avatar]

Membro desde: 13/08/2005 16:03:36
Mensagens: 19
Offline

Foram disparadas duas threads sequencialmente, mas não há garantias de que o resultado seja sempre o mesmo.

O programa não controla a ordem de execução das threads. Quem faz isso é a JVM, que irá escalonar o processador para atender às duas threads simulando um processamento paralelo.

Threads recém criadas têm a mesma prioridade e a JVM escolhe aleatoriamente aquela que será executada.

Para ver como funciona o escalonamento faça testes alterando a prioridade das suas threads.

"Uma ferramenta não vale mais que a perícia de quem a manipula"
fabioEM
GUJ Master
[Avatar]
Membro desde: 13/09/2007 13:34:23
Mensagens: 1041
Offline

thundercas wrote:Dentro do método run() você chama duas vezes o método me(). Por isso o mesmo nome é exibido duas vezes...

No entanto, não é exibido 1-1 ou 2-2, veja abaixo como ficou aqui:


wallace - 1
wallace - 2
gloiac - 1
gloiac - 2


beleza,eu queria saber onde entra o synchronized ?pois se o retirarmos do codigo o resultado defere,estou estudando esta parte mas
nao estou entendendo .O bloqueio de um objeto.No livro explica que este é um exemplo pois
o modificador é synchronized e somente um theads pode acessar um objeto de cada vez,mas
na pratica nao intendi a logica

"Um pouco de ciência nos afasta de Deus. Muito, nos aproxima." (Louis Pasteur)
Conheçam Sócrates: http://www.youtube.com/watch?v=SlJSF-V6yBA
Conheçam a obra social Célio Lemos: http://www.oscl.org.br/site/
Conheçam o Projeto: http://www.youtube.com/watch?v=9-k818tfG6M&feature=youtu.be
Sun Certified Java Programmer 1.5
jdefarge
Thread.start()

Membro desde: 13/11/2007 00:15:18
Mensagens: 44
Offline

Quando se usa a palavra synchronized em um método, toda Thread que acessar esse método irá ANTES obter um lock (trava) do objeto para só então executar o método. Quando a Thread termina a execução do método ela libera o lock pra que outra Thread possa pegar o lock também e executar o método.

E tudo isso (obtenção do lock, execução, liberação do lock) é feito automaticamente quando a Thread chama o método synchronized. E duas threads não podem obter o lock ao mesmo tempo. Isso serve pra controle de concorrência, isto é, impedir que duas Threads chamem o método ao mesmo tempo e gerem dados inconsistentes no objeto. Em resumo, o synchronized faz com que o acesso seja serializado, isto é, uma thread de cada vez chama os métodos synchronized daquele objeto. Tem outros detalhes, mas acho que vc entendeu, certo?

This message was edited 1 time. Last update was at 04/01/2008 22:43:39

ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20580
Localização: Curitiba/PR
Offline

Sim, mas o synchronized não tem nada a ver com esse caso.

O que acontece é o que já falaram, você chama duas vezes o me().

Não há garantias de que você vá obter a mesma palavra duas vezes seguidas. As chances disso ocorrer são grandes, mas não são 100%. Pode ocorrer de, entre uma chamada a me e outra, o SO trocar as duas threads e você ter as duas palavras alternadas como saída. Isso é ainda mais provável num processador dual core.

Agora, embora isso seja possível, é improvável. Por isso talvez você não tenha conseguido obter o resultado que você esperava, o de algumas vezes o programa alternar a impressão dos nomes.

@ViniGodoy - Lattes

Tem dúvidas de Java? Poste no fórum! Não respondo dúvidas de java via MP!

Ponto V! - Desenvolvimento de Jogos Profissional - @Pontov - Facebook
Projeto Towel - Swing de uma forma inteligente (Novo lar do ObjectTableModel e do Auto-Filtro).

Ei... você está usando DefaultTableModel no seu projeto??
Não faça isso! Veja: http://www.guj.com.br/posts/list/15/199067.java#1001295
[WWW]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20580
Localização: Curitiba/PR
Offline

O synchronized faz o bloqueio de uma thread, que está percorrendo um objeto. Para que ele tenha efeito, duas threads tem que tentar entrar no bloco sincronizado do mesmo objeto.

Nenhuma das threads criadas por você percorre o método main. Elas iniciam no run(), imprimem duas vezes e morrem. Por isso, seu synchronized não está servindo para absolutamente nada. Elas também não entram em nenhum bloco sincronizado, já que nem o método run() e nem o me() são sincronizados.

Aqui vai um exemplo do bloco sincronized. Primeiro, vamos declarar uma classe que faz a impressão de qualquer coisa 20 vezes.



Agora, vamos criar 2 classes, que usam essa classe para imprimir "Vinicius" e "Fabio", que usa a impressora 20 vezes (e, portanto, imprime o nome 400x).



Ok, agora dispare esse código com o seguinte main:



O que parece que vai acontecer? Que os nomes serão impressos de 20 em 20, afinal existe uma única impressora e seu método imprime o nome 20 vezes de uma só vez. Assim, dois nomes não vão se intercalar, certo?

Entretanto, ao rodar o programa não é isso que acontece... alguns nomes aparecem intercalados e as vezes a impressora "se perde". Por que isso ocorre?

Porque ambas as threads entram no método print ao mesmo tempo.

Note que eu não chamei o NameWriter de thread, porque ele não é uma thread. Duas threads foram criadas percorrendo objetos do tipo Namewriter e, quando as linhas de execução chamaram o método print, elas se deslocaram para outro objeto. Isso é um conceito muito importante! Threads são as linhas de execução criadas após o start(), não os objetos.

Como evitaríamos isso? O fato é que duas threads não podem "cohabitar" o método print. O método print deveria imprimir tudo de uma thread, e depois tudo de outra. Para fazer essa exclusão mútua, usamos a palavra chave synchronized.

Quando uma thread entra num bloco synchronized, ela tenta obter o objeto ao qual estamos aplicando a sincronização. Esse objeto é chamado de monitor. Se esse objeto estiver disponível, ela segura o monitor e entra no bloco. Quando sair do bloco, ela libera o monitor. Quando uma thread tenta entrar no bloco, mas não consegue obter o monitor, ela simplesmente aguarda até que aquele objeto esteja disponível.

E que objeto é esse? Num bloco synchronized, o objeto é o this. No caso de criarmos esse bloco na impressora, o objeto seria a própria impressora p1. Ou seja, fazer na impressora:


É o mesmo que fazer:


Experimente rodar o código com o synchronized. Você vai ver que o problema não ocorre mais. Os nomes sempre são impressos de 20 em 20.

Isso tem uma importante consequência. Duas threads só serão sincronizadas se o objeto this do bloco synchronized for o mesmo. Experimente manter o bloco synchronized e criar duas impressoras ao invés de uma. Depois, passe uma impressora para cada NameWriter. Você vai notar que o problema "volta a ocorrer". Na verdade, o que acontece é que threads diferentes estão percorrendo impressoras diferentes. Portanto, o this de cada impressora refere-se a uma impressora diferente e não há sincronização.

Isso porque, na verdade, o problema não voltou a ocorrer, você vai notar que os fors nunca se perdem e, apesar de os nomes se intercalarem, os nomes serão impressos 400 vezes. O que você tem é uma execução realmente em paralelo, em duas impressoras diferentes.

Uma das formas de voltar a sincronizar seria fazer as duas impressoras compartilharem um objeto, e fazer o synchronized sobre esse objeto. O objeto monitor pode ser um objeto qualquer. Deixo como exercício para você fazer essa alteração.

Qualquer dúvida é só perguntar.

This message was edited 3 times. Last update was at 19/01/2012 10:57:52


@ViniGodoy - Lattes

Tem dúvidas de Java? Poste no fórum! Não respondo dúvidas de java via MP!

Ponto V! - Desenvolvimento de Jogos Profissional - @Pontov - Facebook
Projeto Towel - Swing de uma forma inteligente (Novo lar do ObjectTableModel e do Auto-Filtro).

Ei... você está usando DefaultTableModel no seu projeto??
Não faça isso! Veja: http://www.guj.com.br/posts/list/15/199067.java#1001295
[WWW]
LPJava
GUJ Hacker

Membro desde: 18/04/2006 12:50:23
Mensagens: 5524
Localização: Bahia/Porto Alegre
Offline

depois dessa aula do vinny nem vou postar minha sugestao hehe show de bola.. esse cara é fera demais! parabens vinny!!

Sun Certified Java Programmer 5.0
Blog:http://www.camilolopes.com
Twitter:www.twitter.com/camilolope
Linkedin: http://br.linkedin.com/in/camilolopes
Curso online OCPJP: http://pro.imasters.com.br/online/cursos/preparatorio-para-certificacao-java-ocjp
Autor livro Guia SCJP & JEE c/ Frameworks: http://blog.camilolopes.com.br/livrosrevistaspalestras/
[WWW]
fabioEM
GUJ Master
[Avatar]
Membro desde: 13/09/2007 13:34:23
Mensagens: 1041
Offline


Bom Vinny muito obrigado pelo esclarecimento!!Esta parte de threads estou vendo agora e to tendo dificuldades mas agora melhorou bastante !!
valeu mesmo!!

"Um pouco de ciência nos afasta de Deus. Muito, nos aproxima." (Louis Pasteur)
Conheçam Sócrates: http://www.youtube.com/watch?v=SlJSF-V6yBA
Conheçam a obra social Célio Lemos: http://www.oscl.org.br/site/
Conheçam o Projeto: http://www.youtube.com/watch?v=9-k818tfG6M&feature=youtu.be
Sun Certified Java Programmer 1.5
fabioEM
GUJ Master
[Avatar]
Membro desde: 13/09/2007 13:34:23
Mensagens: 1041
Offline


Ola Vinny,so para ver se entendi mesmo ou fiz confusao:
Para garantir o bloqueio de um objeto logo uso synchronized assim o metodo ele será acessado por um threads de cada vez
fiz um exemplo aqui mais ou menos como tu falaste:
eu notei que para ter certeza do bloqueio entao para que emprima Hokuto,Hokuto.....20 vezes e depois Noken,Noken...20 vezes tenho que synchronizar o metodo run.
se fizer porem synchronizar o metodo impr() nao vai dar sempre certo, as vezes ele escalona os threads,e isso mesmo? Achavo que seria equivalente como tambem
synchronizar uma parte de codigo como no teu exemplo synchronized(this)
a ultima duvida é?pq se colocar um metodo static sentro de impr() o bloqueio nao é mais garantido?


a ultima duvida é?pq se colocar um metodo static sentro de impr() o bloqueio nao é mais garantido?

valeu!!

"Um pouco de ciência nos afasta de Deus. Muito, nos aproxima." (Louis Pasteur)
Conheçam Sócrates: http://www.youtube.com/watch?v=SlJSF-V6yBA
Conheçam a obra social Célio Lemos: http://www.oscl.org.br/site/
Conheçam o Projeto: http://www.youtube.com/watch?v=9-k818tfG6M&feature=youtu.be
Sun Certified Java Programmer 1.5
jdefarge
Thread.start()

Membro desde: 13/11/2007 00:15:18
Mensagens: 44
Offline

Só tem umas pequenas imprecisões na explicação do Vini. Vejamos:


Quando uma thread entra num bloco synchronized, ela tenta obter o objeto ao qual estamos aplicando a sincronização. Esse objeto é chamado de monitor. Se esse objeto estiver disponível, ela segura o monitor e entra no bloco. Quando sair do bloco, ela libera o monitor. Quando uma thread tenta entrar no bloco, mas não consegue obter o monitor, ela simplesmente aguarda até que aquele objeto esteja disponível.


uma thread não tenta obter o objeto, Vini, ela tenta obter o lock do objeto. E monitor é o nome da técnica, criado por Hoare na década de 70, que permite implementar esse tipo de exclusão mútua. Então ele não segura o monitor, mas sim o lock associado ao objeto.
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20580
Localização: Curitiba/PR
Offline

jdefarge wrote:Só tem umas pequenas imprecisões na explicação do Vini. Vejamos:


Quando uma thread entra num bloco synchronized, ela tenta obter o objeto ao qual estamos aplicando a sincronização. Esse objeto é chamado de monitor. Se esse objeto estiver disponível, ela segura o monitor e entra no bloco. Quando sair do bloco, ela libera o monitor. Quando uma thread tenta entrar no bloco, mas não consegue obter o monitor, ela simplesmente aguarda até que aquele objeto esteja disponível.


uma thread não tenta obter o objeto, Vini, ela tenta obter o lock do objeto. E monitor é o nome da técnica, criado por Hoare na década de 70, que permite implementar esse tipo de exclusão mútua. Então ele não segura o monitor, mas sim o lock associado ao objeto.


Eu sei que a explicação não era tão precisa. É aquele negócio, abri um pouco mão da absoluta precisão técnica em prol da didática.

Eu já tentei explicar locks de objeto aqui e vi que não tive muito sucesso. Entrar em detalhes da terminologia do monitor não ajuda muito também. Melhor deixar o pessoal entender a mecânica, para depois de amadurecidos no conceito entender detalhes como esse.

This message was edited 1 time. Last update was at 07/01/2008 09:44:44


@ViniGodoy - Lattes

Tem dúvidas de Java? Poste no fórum! Não respondo dúvidas de java via MP!

Ponto V! - Desenvolvimento de Jogos Profissional - @Pontov - Facebook
Projeto Towel - Swing de uma forma inteligente (Novo lar do ObjectTableModel e do Auto-Filtro).

Ei... você está usando DefaultTableModel no seu projeto??
Não faça isso! Veja: http://www.guj.com.br/posts/list/15/199067.java#1001295
[WWW]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20580
Localização: Curitiba/PR
Offline

fabioEM wrote:
eu notei que para ter certeza do bloqueio entao para que emprima Hokuto,Hokuto.....20 vezes e depois Noken,Noken...20 vezes tenho que synchronizar o metodo run.


Não... cada thread inicia num objeto com seu próprio run(). Se você tem 2 objetos, em 2 threads diferentes, não há sincronização. Há paralelismo.

fabioEM wrote:
se fizer porem synchronizar o metodo impr() nao vai dar sempre certo, as vezes ele escalona os threads,e isso mesmo?


Não. Enquanto uma thread estiver no método impr(), a outra vai ter que esperar. Se ela for escalonada, ela tentará obter o lock do monitor e irá voltar a dormir. A thread que está dentro do impr() cedo ou tarde acorda e não libera o lock enquanto não terminar o processamento.

fabioEM wrote:
Achavo que seria equivalente como tambem synchronizar uma parte de codigo como no teu exemplo synchronized(this)
a ultima duvida é?pq se colocar um metodo static sentro de impr() o bloqueio nao é mais garantido?


O bloqueio continua garantido, mas não mais para um objeto da impressora, mas a exclusão ocorrerá em todas as classes da impressora. Fazer o bloqueio num método synchronized é mais ou menos o mesmo que fazer:

This message was edited 1 time. Last update was at 07/01/2008 09:45:21


@ViniGodoy - Lattes

Tem dúvidas de Java? Poste no fórum! Não respondo dúvidas de java via MP!

Ponto V! - Desenvolvimento de Jogos Profissional - @Pontov - Facebook
Projeto Towel - Swing de uma forma inteligente (Novo lar do ObjectTableModel e do Auto-Filtro).

Ei... você está usando DefaultTableModel no seu projeto??
Não faça isso! Veja: http://www.guj.com.br/posts/list/15/199067.java#1001295
[WWW]
 
Índice dos Fóruns » Java Básico
Ir para:   
Powered by JForum 2.1.8 © JForum Team