Duvida Thread

5 respostas
Raff

Pessoal olha eu de novo aqui com duvida de Thread…

class SpreadSheet {
        int cellA1, cellA2, cellA3;

        synchronized int sumRow(  ) {
            return cellA1 + cellA2 + cellA3;
        }

        synchronized void setRow( int a1, int a2, int a3 ) {
            cellA1 = a1;
            cellA2 = a2;
            cellA3 = a3;
        }
        ...
    }

A minha dúvida é a seguinte:
Se um thread está no meio da execução do metodo setRow(), quando outro thread chama o sumRow() o que acontecerá alguem poderia me explicar ???
Ele irá executar normalmente ou ficará bloqueado, se for ficar bloqueado alguem poderia me explicar?

5 Respostas

Java_Boy

Raff

Cara, imagino que ele nao seja executado no mesmo tempo, cairá numa lista de espera de execucao, é oque o synchronized possibilta fazer :P, possa estar errado, mas basicamente é isso.

[]s

ViniGodoy

Isso mesmo.

Quando um thread tenta entrar num método sincronizado, ele faz o seguinte:

  1. Verifica se algum thread está num trecho sincronizado daquele objeto de lock. Nesse caso, como o método foi declarado synchronized o objeto de lock é o próprio objeto (this);

  2. Se ninguém estiver lá, ela adquire o lock e entra no bloco de código;

  3. Se alguém estiver com o lock, a thread dorme, até que seja notificada ou que o lock seja liberado;

Alguns detalhes. Se a thread for notificada, mas o objeto de trava ainda não tiver sido liberado, a thread volta a dormir.

Se mais de uma thread estiver esperando pelo trecho sincronizado, não há garantia absolutamente nenhuma de qual delas irá acordar e percorrer esse trecho. Essa decisão, como tudo em threads, é deixada para o SO, que não usa nenhum critério que possamos prever (e pode mudar de SO para SO). Aliás, pode parecer tentador, mas mudar a prioridade da thread também não dá garantia nenhuma nesse caso, e geralmente, gera mais mal do que bem.

Note que, no caso da sua classe, se alguém estiver executando setRow() e alguém tentar executar sumRow(), a thread do sum irá ser colocada para dormir até que setRow() termine. Isso porque ambos os métodos usam this como lock do synchronized e nesse caso isso é o correto mesmo.

Se você quisesse fazer com que uma thread pudesse acessar cada método ao mesmo tempo (mas que somente uma thread por vez pudesse entrar no método em si), você teria que usar locks diferentes. Isso é muito comum em sockets, onde você tem threads que escrevem no socket e outras que lêem do socket. Mas duas threads ao mesmo tempo não podem tentar fazer a mesma operação.

anderson.bonavides

Como o nosso amigo falou acima acredito que cairá em espera. Syncronized fala que se um meto é syncronized ele não é interrompido por outra thread. Como o K&B fala se temos alguêm realizando um saque para uma conta de 10 reais não vamos deixar algum outro cliente da mesma conta retirar 10 novamente no mesmo tempo o que deixaria um saldo negativo. Então syncronized não deixa q uma thread interrompa outra no meio da execução.

imagine um saldo de 10 reais e 5 menbros da familia tentando retirar 10 reais, cada um com seu cartão tudo no mesmo instante de tempo?
Inviável não é? Porém não é impossível.

Bem axo q é isso!
Se eu estiver errado por favor alguêm me fale, pois não sou sábio!

:wink:

Raff

Se eu fizer assim Vini então eu consegui executar dois thread pseudoparalelos já que o Objeto de lock é diferente ?

class SpreadSheet {
        int cellA1, cellA2, cellA3;
        Aluno a = new Aluno();
         int sumRow(  ) {
          synchronized(a){
                        //faz qualquer coisa aqui....
                 }
            return cellA1 + cellA2 + cellA3;
        }

        synchronized void setRow( int a1, int a2, int a3 ) {
            cellA1 = a1;
            cellA2 = a2;
            cellA3 = a3;
        }
        ...
    }

TIpo Vini foi isso que eu entendi será ? :roll:

ViniGodoy

É isso mesmo. Só um comentário, embora a Kathy use objetos completos para locks, não é uma boa prática fazer isso... O ideal é fazer com um objeto simples, onde você não corre o risco dele mesmo fazer um sincronized (this) internamente. Assim:

public class SocketWorker {
   private Socket socket;

   //Um objeto mega simples, só para servir de lock
   private int[] writeLock = new int[0];    
   private int[] readLock = new int[0]; 

   private int readBytes = 0; //Um contador de bytes lidos
   private int writtenBytes = 0; //Um contador de bytes escritos

   public void readFromSocket() {
       //Vamos travar somente as threads interessadas em leitura
       synchronized (readLock) {
            //Faz a leitura do socket aqui, dispara eventos, ou sei lá.
            //Também incrementa readBytes
       }
    }

   public void writeInSocket(byte[] bytes) {
       //Aqui interessa enfileirar só quem faz write no socket    
       synchronized (writeLock) {
              //Faz a escrita no socket.
             //Também incrementa writtenBytes
       }
    }

    public int getWrittenBytes() {
       //Só vamos ler a variável quando não está havendo escrita
       synchronized (writeLock) { 
           return bytesWritten; 
       }
     }

    public int getReadBytes() {
       //Só vamos ler a variável quando não está havendo leitura
       synchronized (readLock) { 
           return bytesRead; 
       }
     }
}
Criado 7 de novembro de 2007
Ultima resposta 7 de nov. de 2007
Respostas 5
Participantes 4