Synchronized

12 respostas
E

Boa Dia a Todos,

Estou com uma dúvida a respeito do synchronized.

Quando é declarado um médoto como synchronized ele só pode ser acessado por um objeto de cada vez correto?

Estava lendo sobre outros modificadores, e em mais de um artigo li que: “Um método synchronized só pode ser acessado por uma thread de cada vez”

queria saber se o synchronized só sincroniza a execução do método para as theads mesmo ou não, sincroniza execução para qualquer objeto?

desde já agradeço

12 Respostas

T

Este código

public synchronized void method () {
    ...
}

é completamente equivalente a este:

public void method () {
    synchronized (this) {
        ...
    }
}

assim como este código:

class Klass {
    public static synchronized void method () {
        ...
    }
}

é equivalente a este:

class Klass {
    public static void method () {
        synchronized (Klass.class) {
            ...
        }
    }
}

Se você entender como funciona a sincronização sobre um objeto, então fica muito mais fácil - o atributo “synchronized” em um método só existe em tempo de compilação, já que é uma simples “abreviatura” do código mais extenso que mostrei.

L

Isso mesmo,
muito bom exemplo…

“Um método synchronized só pode ser acessado por uma thread de cada vez”

synchronized só pode ser aplicado para métodos, não variaveis nem classes, sómente methods =)

Tchauzin!

E

Bom Dia Tiago,

entendi o que vc explicou , mas a minha dívuda é :

Declarando um médoto synchronized (pode ser de qualquer um dos 2 modos que vc mostrou) será sincronizado o acesso ao método para qualquer objeto q tente fazer esse acesso , ou não, só sincroniza o acesso das threads?

estou com essa dúvida pois o conceito que tinha é que usando synchronized o método vai ser acessado por apenas um objeto de cada vez(independendo de o objeto ser uma thead ou não), mas lendo em outros artigos fala que sincroniza o acesso de uma thead de cada vez.

J

Só protege contra acesso simultâneo de threads, pois só threads podem executar simultaneamente, se sua aplicação não usa thread ela terá apenas uma linha de execução, e portanto não há necessidade de sincronização pois o código nunca será executado mais de uma vez ao mesmo tempo.

V

Tenha em mente o seguinte.

Uma thread não é um objeto.

Existe um objeto que descreve uma Thread, mas ele não é a Thread em si. A thread é simplesmente a linha de execução que é criada quando você chama start() e que vai durar até que esse método acabe.

Após o thread.start(), todos os métodos evocados pelo seu Runnable, independentemente do objeto em que eles estejam, estarão sendo chamados na nova thread.

Dá uma olhada também nesse tópico:
http://www.guj.com.br/posts/list/49947.java

O synchronized é um mecanismo para controle de threads, não objetos.

E

entendi o q vc explicou vini.

só tinha ficado com esse conceito pq em um projeto q participei, na camada de persistência quanto ia incluir um registro o método de inclusão(que não era executado por uma thread) era sincronizado, isso devido ao banco (oracle) não estar com sequences, então antes de fazer o insert tinha q pegar o último id e somar 1.
Foi feito isso para garantir que se mais de uma inclusão fosse feita ao mesmo tempo não dar um possível erro de chave duplicada, uma vez q esse id era a chave do registro.

agora uma curiosidade, teria outro jeito de garantir isso (não dar um possível erro de chave duplicada) sem ser o uso das sequences? usar o synchronized assim foi errado?

V

No caso do Oracle, o problema é ainda maior. Afinal, você provavelmente terá várias aplicações acessando o Oracle. Como Threads e sincronização se aplicam apenas para o contexto de uma só VM, elas não servirão para resolver 100% do problema.

Nesse caso, só usando um recurso de alguém na rede mesmo, seja no banco de dados, ou no seu servidor de aplicações, ou num framework de distribuição. Tudo vai depender da arquitetura escolhida. Mas certamente recursos do BD (Sequences/Oracle) não são a única forma possível de se resolver os problemas.

L

onde vi o uso do synchoronized a respeito a thread é quando vc tem duas threads tentando acessar o mesmo objeto e manipular imagine ai o metodo suaconta() que tem la seus $$ entao é interessante que qdo vc estiver manipulando ela que alguem q vc deixou ter outro cartao da sua conta nao manipule essa conta qdo vc estiver manipulando, ou seja, so manipule qdo vc terminar… isso acontece sempre qdo vamos ao caixa eletronico porem eh obscuro para o cliente… é um exemplo bem basico …mais interessante hehe!!

espero ter ajudado… seu eu tiver errado a galera me corrige… ae!!

flw!!

V

É Camilo, mas embora o exemplo do banco seja bastante didático, lembre-se que cada caixa automático será um computador e, portanto, cada um terá seu próprio processador, memória e etc. Assim, não há concorrência entre as threads de diferentes caixas. Pelo menos não onde o java possa resolver por si só.

Nesse caso, só usar synchronized não é suficiente. Você ou terá que ter uma entidade centralizadora (o servidor do banco) ou terá que investir em algum algoritmo de mensagens distribuídas.

E

então pelo que entendi não foi errada a implementação que foi feita no referido projeto, foi apenas uma forma de contornar um problema.

pra mim então ficou mais claro que o synchronized sincroniza o método independendo de que objeto esta tentando acessar (concordando com o que foi explicado que só com as threds podemos ter processos simultaneos ), mas minha preocupação é se uma pergunta dessas cair na prove de certificação seria errado dizer que o sincronized sincroniza o médotos de acesso a objetos? será que considerariam somente a sincronização das threads por causa do conceito da simultaniedade?
o que vcs me aconselham?

V

A solução com synchronized do projeto resolve o problema, desde que, apenas uma máquina na rede use o Oracle de cada vez. Se várias forem usar, teriam que partir para sequences mesmo.

Não estaria errada a resposta. O synchronized efetivamente sincroniza o acesso da thread a um trecho de código qualquer.

J

ezellis:
então pelo que entendi não foi errada a implementação que foi feita no referido projeto, foi apenas uma forma de contornar um problema.

pra mim então ficou mais claro que o synchronized sincroniza o método independendo de que objeto esta tentando acessar (concordando com o que foi explicado que só com as threds podemos ter processos simultaneos ), mas minha preocupação é se uma pergunta dessas cair na prove de certificação seria errado dizer que o sincronized sincroniza o médotos de acesso a objetos? será que considerariam somente a sincronização das threads por causa do conceito da simultaniedade?
o que vcs me aconselham?

ezelis, vale lembrar que o modificador synchronized no método sincroniza não somente aquele método (para que somente um thread o acesse), mas sim todo acesso ao objeto em questão. Desta forma se vc tiver dois threads que ao mesmo tempo tentem acessar o objeto, mesmo sendo métodos diferentes, somente um ganhará o acesso e o outro aguradará que o primeiro termine a execução do método que chamou.
Se vc quiser sincronizar somente um método, vc deverá criar um objeto de lock.

class T{
   Object lock1 = new Object();
   Object lock2 = new Object();

   void metodo1(){
        synchronized(lock1){
           ...
        }
   }
   void metodo2(){
        synchronized(lock2){
           ...
        }
   }
   void metodo3(){
      ...
   }
}

no exemplo, somente um thread pode acessar o metodo1 de cada vez, o mesmo acontece para o metodo 2, mas um thread pode executar o metodo 1 enquanto o outro executa o metodo 2. O metodo 3 não está sincronizado com nada, pode ter acesso simultâneo e é a própria casa da mãe joana :smiley:

Criado 23 de janeiro de 2007
Ultima resposta 26 de jan. de 2007
Respostas 12
Participantes 7