Pergunta

Pode qualquer um dizer-me a vantagem de método sincronizado sobre o bloco sincronizado com um exemplo?

Foi útil?

Solução

Alguém pode me dizer a vantagem do método sincronizado sobre o bloco sincronizado com um exemplo? Obrigado.

Não há uma clara vantagem de usar método sincronizado sobre o bloco.

Talvez o único (mas eu não chamaria isso de uma vantagem) é que você não precisa incluir o this referência de objeto.

Método:

public synchronized void method() { // blocks "this" from here.... 
    ...
    ...
    ...
} // to here

Block:

public void method() { 
    synchronized( this ) { // blocks "this" from here .... 
        ....
        ....
        ....
    }  // to here...
}

Veja? Nenhuma vantagem em tudo.

Blocos do tem vantagens sobre os métodos, porém, principalmente na flexibilidade, porque você pode usar outro objeto como bloqueio enquanto sincronizar o método seria bloquear todo o objeto.

Compare:

// locks the whole object
... 
private synchronized void someInputRelatedWork() {
    ... 
}
private synchronized void someOutputRelatedWork() {
    ... 
}

vs.

// Using specific locks
Object inputLock = new Object();
Object outputLock = new Object();

private void someInputRelatedWork() {
    synchronized(inputLock) { 
        ... 
    } 
}
private void someOutputRelatedWork() {
    synchronized(outputLock) { 
        ... 
    }
}

Além disso, se o método cresce você ainda pode manter a seção sincronizado separados:

 private void method() {
     ... code here
     ... code here
     ... code here
    synchronized( lock ) { 
        ... very few lines of code here
    }
     ... code here
     ... code here
     ... code here
     ... code here
}

Outras dicas

A única diferença real é que um bloco sincronizado pode escolher qual objeto ele sincroniza diante. Um método sincronizado só pode utilizar 'this' (ou a ocorrência de classe correspondente por um método de classe sincronizada). Por exemplo, estes são semanticamente equivalentes:

synchronized void foo() {
  ...
}

void foo() {
    synchronized (this) {
      ...
    }
}

O último é mais flexível, uma vez que pode competir para o bloqueio associado do qualquer objeto, muitas vezes uma variável de membro. É também mais granular, porque você pode ter código concorrente executar antes e depois do bloco, mas ainda dentro do método. Claro, você pode facilmente usar um método sincronizado por refatoração do código concorrente em métodos não-sincronizado separadas. Use o que torna o código mais compreensível.

Synchronized Método

Pros:

  • O IDE pode indicar os métodos sincronizados.
  • A sintaxe é mais compacto.
  • Forças dividir os blocos sincronizados com métodos distintos.

Contras:

  • sincronizado com este e assim torna possível a pessoas de fora para sincronizar a ele também.
  • É mais difícil de mover o código fora do bloco sincronizado.

Synchronized bloquear

Pros:

  • Permite usar uma variável privada para o bloqueio e assim forçar a fechadura para ficar dentro da classe.
  • blocos sincronizados pode ser encontrada através de pesquisa referências à variável.

Contras:

  • A sintaxe é mais complicado e por isso torna o código mais difícil de ler.

Pessoalmente eu prefiro usar métodos sincronizados com aulas focado apenas à coisa que precisa de sincronização. Essa classe deve ser tão pequena quanto possível e por isso deve ser fácil para rever a sincronização. Outros não precisa se preocupar com a sincronização.

A principal diferença é que se você usar um bloco sincronizado você pode bloquear em um objeto diferente de este , que permite ser muito mais flexível.

Suponha que você tenha uma fila de mensagens e vários produtores e consumidores de mensagens. Nós não queremos produtores de interferir uns com os outros, mas os consumidores devem ser capazes de recuperar mensagens sem ter que esperar para os produtores. Então, nós apenas criar um objeto

Object writeLock = new Object();

E a partir de agora cada vez que um produtor quer adicionar uma nova mensagem nós apenas bloquear em que:

synchronized(writeLock){
  // do something
}

Assim, os consumidores ainda podem ler, e os produtores serão bloqueados.

método sincronizado

métodos sincronizados ter dois efeitos.
Em primeiro lugar, quando um fio é a execução de um método sincronizado para um objecto, todos os outros segmentos que invocam métodos sincronizados para o mesmo bloco de objecto (suspender a execução) até que o primeiro segmento é feito com o objeto.

Em segundo lugar, quando um sincronizados saídas método, ele automaticamente estabelece uma acontece-antes de relacionamento com qualquer invocação posterior de um método sincronizado para o mesmo objeto. Isso garante que alterações no estado do objeto são visíveis para todos os tópicos.

Note que os construtores não podem ser sincronizados - usando a palavra-chave sincronizado com um construtor é um erro de sintaxe. Sincronizando construtores não faz sentido, porque só o segmento que cria um objeto deve ter acesso a ele enquanto ele está sendo construído.

Declaração sincronizada

Ao contrário dos métodos sincronizados, declarações sincronizados deve especificar o objeto que fornece o bloqueio intrínseca: Na maioria das vezes eu uso isso para o acesso de sincronização para uma lista ou mapa, mas eu não quero bloquear o acesso a todos os métodos do objeto.

Q: Intrínseca Locks e sincronização A sincronização é construída em torno de uma entidade interna conhecido como o fechamento intrínseca ou monitor de bloqueio. (A especificação API muitas vezes refere-se a esta entidade simplesmente como um "monitor.") Fechaduras intrínsecos desempenhar um papel em ambos os aspectos de sincronização: fazer cumprir acesso exclusivo ao estado de um objeto e estabelecer acontece-antes de relacionamentos que são essenciais para a visibilidade.

Cada objeto tem um bloqueio intrínseco associado a ele. Por convenção, um segmento que precisa de acesso exclusivo e consistente para campos de um objeto tem de adquirir bloqueio intrínseca do objeto antes de acessá-los, e, em seguida, liberar o bloqueio intrínseca quando ele é feito com eles. Um fio é dito que possui o bloqueio intrínseca entre o tempo que adquiriu o bloqueio e liberado o bloqueio. Enquanto um segmento possui um bloqueio intrínseco, nenhuma outra thread pode adquirir o mesmo bloqueio. O outro segmento vai bloquear quando tenta adquirir o bloqueio.

package test;

public class SynchTest implements Runnable {  
    private int c = 0;

    public static void main(String[] args) {
        new SynchTest().test();
    }

    public void test() {
        // Create the object with the run() method
        Runnable runnable = new SynchTest();
        Runnable runnable2 = new SynchTest();
        // Create the thread supplying it with the runnable object
        Thread thread = new Thread(runnable,"thread-1");
        Thread thread2 = new Thread(runnable,"thread-2");
//      Here the key point is passing same object, if you pass runnable2 for thread2,
//      then its not applicable for synchronization test and that wont give expected
//      output Synchronization method means "it is not possible for two invocations
//      of synchronized methods on the same object to interleave"

        // Start the thread
        thread.start();
        thread2.start();
    }

    public synchronized  void increment() {
        System.out.println("Begin thread " + Thread.currentThread().getName());
        System.out.println(this.hashCode() + "Value of C = " + c);
//      If we uncomment this for synchronized block, then the result would be different
//      synchronized(this) {
            for (int i = 0; i < 9999999; i++) {
                c += i;
            }
//      }
        System.out.println("End thread " + Thread.currentThread().getName());
    }

//    public synchronized void decrement() {
//        System.out.println("Decrement " + Thread.currentThread().getName());
//    }

    public int value() {
        return c;
    }

    @Override
    public void run() {
        this.increment();
    }
}

Cruz verificar diferentes saídas com método sincronizado, bloco e sem sincronização.

Nota:. estática métodos sincronizados e blocos de trabalho no objeto Class

public class MyClass {
   // locks MyClass.class
   public static synchronized void foo() {
// do something
   }

   // similar
   public static void foo() {
      synchronized(MyClass.class) {
// do something
      }
   }
}

Quando compilador Java converte o código fonte para código de byte, ele lida com métodos sincronizados e blocos sincronizados de forma muito diferente.

Quando a JVM executa um método sincronizado, os executores identifica segmento que estrutura method_info do método tem a flag ACC_SYNCHRONIZED, então ele automaticamente adquire bloqueio do objeto, chama o método, e libera o bloqueio. Se ocorrer uma exceção, o segmento libera automaticamente o bloqueio.

Sincronizando um bloco método, por outro lado, evita a JVM apoio embutido para a aquisição e bloqueio excepção manipulação de um objecto e requer que a funcionalidade seja explicitamente escritas em código de bites. Se você ler o código de byte para um método com um bloco sincronizado, você vai ver mais do que uma dúzia de operações adicionais para gerenciar essa funcionalidade.

Isso mostra chamadas para gerar tanto um método sincronizado e um bloco sincronizado:

public class SynchronizationExample {
    private int i;

    public synchronized int synchronizedMethodGet() {
        return i;
    }

    public int synchronizedBlockGet() {
        synchronized( this ) {
            return i;
        }
    }
}

O método synchronizedMethodGet() gera a sequência de código byte:

0:  aload_0
1:  getfield
2:  nop
3:  iconst_m1
4:  ireturn

E aqui está o código de byte a partir do método synchronizedBlockGet():

0:  aload_0
1:  dup
2:  astore_1
3:  monitorenter
4:  aload_0
5:  getfield
6:  nop
7:  iconst_m1
8:  aload_1
9:  monitorexit
10: ireturn
11: astore_2
12: aload_1
13: monitorexit
14: aload_2
15: athrow

Uma diferença significativa entre o método sincronizado e bloco é que, o bloco sincronizado geralmente reduzir âmbito da fechadura. Como âmbito da fechadura é inversamente proporcional ao desempenho, é sempre melhor para bloquear única seção crítica do código. Um dos melhores exemplo do uso de bloco sincronizado é dobro verificado bloqueio no padrão Singleton , onde em vez de bloqueio método getInstance() todo só bloquear secção crítica do código que é utilizado para criar a instância Singleton. Isto melhora o desempenho de bloqueio drasticamente porque só é necessário uma ou duas vezes.

Enquanto estiver usando métodos sincronizados, você terá que tomar cuidado extra se você misturar tanto estáticos sincronizados e não estático métodos sincronizados.

Na maioria das vezes eu uso isso para o acesso de sincronização para uma lista ou mapa, mas eu não quero bloquear o acesso a todos os métodos do objeto.

No código a seguir um fio modificar a lista não irá bloquear à espera de um segmento que está modificando o mapa. Se os métodos foram sincronizados no objeto, em seguida, cada método teria que esperar, embora as modificações que eles estão fazendo não iria conflitos.

private List<Foo> myList = new ArrayList<Foo>();
private Map<String,Bar) myMap = new HashMap<String,Bar>();

public void put( String s, Bar b ) {
  synchronized( myMap ) {
    myMap.put( s,b );
    // then some thing that may take a while like a database access or RPC or notifying listeners
  }
}

public void hasKey( String s, ) {
  synchronized( myMap ) {
    myMap.hasKey( s );
  }
}

public void add( Foo f ) {
  synchronized( myList ) {
    myList.add( f );
// then some thing that may take a while like a database access or RPC or notifying listeners
  }
}

public Thing getMedianFoo() {
  Foo med = null;
  synchronized( myList ) {
    Collections.sort(myList);
    med = myList.get(myList.size()/2); 
  }
  return med;
}

Com blocos sincronizados, você pode ter vários sincronizadores, de modo que várias coisas simultâneas, mas não conflitantes pode ir ao mesmo tempo.

métodos sincronizados pode ser verificado usando a reflexão API. Isso pode ser útil para testar alguns contratos, tais como todos os métodos no modelo são sincronizados .

O seguinte fragmento imprime todos os métodos sincronizados de Hashtable:

for (Method m : Hashtable.class.getMethods()) {
        if (Modifier.isSynchronized(m.getModifiers())) {
            System.out.println(m);
        }
}

Nota importante sobre a utilização do bloco sincronizado: cuidado com o que você usa como objeto de bloqueio

O fragmento de código de user2277816 acima ilustra este ponto em que uma referência a um literal de cadeia é utilizado como objecto de bloqueio. Perceba que seqüência de literais são automaticamente internado em Java e você deve começar a ver o problema: cada parte do código que sincroniza sobre o "bloqueio" literal, compartilha o mesmo bloqueio! Isso pode facilmente levar a impasses com peças completamente alheios de código.

Não é apenas objetos String que você precisa ter cuidado com. primitivos encaixotados são também um perigo, uma vez autoboxing e os métodos valueOf pode reutilizar os mesmos objetos, dependendo do valor.

Para mais informações consulte: https: / /www.securecoding.cert.org/confluence/display/java/LCK01-J.+Do+not+synchronize+on+objects+that+may+be+reused

Muitas vezes usando um bloqueio em um nível método é muito rude. Por que trancar um pedaço de código que não acessar quaisquer recursos compartilhados por trancar um método inteiro. Uma vez que cada objeto tem um bloqueio, você pode criar objetos fictícios para implementar a sincronização de nível de bloco. O nível de bloco é mais eficiente porque não bloquear o método inteiro.

Aqui alguns exemplos

Método Nível

class MethodLevel {

  //shared among threads
SharedResource x, y ;

public void synchronized method1() {
   //multiple threads can't access
}
public void synchronized method2() {
  //multiple threads can't access
}

 public void method3() {
  //not synchronized
  //multiple threads can access
 }
}

Bloco de Nível

class BlockLevel {
  //shared among threads
  SharedResource x, y ;

  //dummy objects for locking
  Object xLock = new Object();
  Object yLock = new Object();

    public void method1() {
     synchronized(xLock){
    //access x here. thread safe
    }

    //do something here but don't use SharedResource x, y
    // because will not be thread-safe
     synchronized(xLock) {
       synchronized(yLock) {
      //access x,y here. thread safe
      }
     }

     //do something here but don't use SharedResource x, y
     //because will not be thread-safe
    }//end of method1
 }

[Edit]

Para Collection como Vector e Hashtable eles são sincronizados quando ArrayList ou HashMap não são e você precisa de definir sincronizado palavra-chave ou invocar coleções método sincronizado:

Map myMap = Collections.synchronizedMap (myMap); // single lock for the entire map
List myList = Collections.synchronizedList (myList); // single lock for the entire list

A única diferença: blocos sincronizados permite bloqueio granular ao contrário método sincronizado

bloco ou métodos Basicamente synchronized têm sido usados ??para código thread-safe gravação, evitando erros de inconsistência memória.

Esta questão é muito antiga e muitas coisas foram alterados durante os últimos 7 anos. Novas construções de programação foram introduzidos para a segurança do thread.

Você pode conseguir a segurança do thread usando avançada simultaneidade API em vez de blocos synchronied. Esta documentação página oferece boas construções de programação para alcançar a segurança do thread.

Bloquear Objetos fortes idiomas de bloqueio apoio que simplificam muitas aplicações simultâneas.

Executores definir uma API de alto nível para lançar e gerir threads. implementações do executor fornecidos pelo java.util.concurrent fornecer gerenciamento de pool de threads adequado para aplicações em larga escala.

simultâneas coleções torná-lo mais fácil de gerenciar grandes coleções de dados, e pode reduzir muito a necessidade de sincronização.

Variáveis ??Atomic têm características que minimizam erros de consistência de sincronização e ajuda memória evitar.

ThreadLocalRandom (no JDK 7) proporciona a geração eficiente de números pseudo-aleatórios a partir de vários segmentos.

Melhor substituto para sincronizado é ReentrantLock , que usa Lock API

Um bloqueio de exclusão mútua de reentrada com o mesmo comportamento básico e semântica como o bloqueio implícito do monitor acessado usando métodos e declarações sincronizadas, mas com capacidades alargadas.

Exemplo com fechaduras:

class X {
   private final ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() {
     lock.lock();  // block until condition holds
     try {
       // ... method body
     } finally {
       lock.unlock()
     }
   }
 }

Consulte java.util .concurrent e pacotes java.util.concurrent.atomic também para outras construções de programação.

Consulte esta questão relacionada demasiado:

sincronização vs bloqueio

método sincronizado é usado para bloqueio de todos os objetos bloco sincronizado é usado para objeto de bloqueio específica

Em geral estes são basicamente o mesmo além de ser explícito sobre o monitor do objeto que está sendo usado contra o implícita este objeto. Uma desvantagem de métodos sincronizados que eu acho que às vezes é esquecido é que, ao usar o "presente" de referência para sincronizar em que você está deixando em aberto a possibilidade de objetos externos de bloqueio no mesmo objeto. Isso pode ser um erro muito sutil se você correr para ele. Sincronizando em um objeto explícito interna ou outro campo existente pode evitar esse problema, encapsulando completamente a sincronização.

Como já foi dito bloco aqui sincronizado pode usar variável definida pelo usuário como bloqueio de objeto, quando sincronizado usa a função única "isto". E, claro, você pode manipular com áreas de sua função que devem ser sincronizados. Mas todo mundo diz que não há diferença entre a função sincronizada e bloco que cobre função inteira usando "isto" como objeto de bloqueio. Isso não é verdade, diferença está em código de bytes que serão gerados em ambas as situações. Em caso de utilização do bloco sincronizado deve ser alocado variável local que detém referência a "isto". E, como resultado, teremos um pouco maior tamanho para a função (não é relevante se você tiver apenas poucos número de funções).

explicação mais detalhada da diferença que você pode encontrar aqui: http://www.artima.com/insidejvm/ed2/threadsynchP.html

Em caso de métodos sincronizados, bloqueio será adquirido em um objeto. Mas se você ir com bloco sincronizado você tem uma opção para especificar um objeto sobre o qual o bloqueio será adquirido.

Exemplo:

    Class Example {
    String test = "abc";
    // lock will be acquired on String  test object.
    synchronized (test) {
        // do something
    }

   lock will be acquired on Example Object
   public synchronized void testMethod() {
     // do some thing
   } 

   }

Eu sei que isto é uma questão de idade, mas com a minha leitura rápida das respostas aqui, eu realmente não ver ninguém mencionar que, por vezes, um método synchronized pode ser o errado fechadura.
De Java Concurrency in Practice (pg 72.):

public class ListHelper<E> {
  public List<E> list = Collections.syncrhonizedList(new ArrayList<>());
...

public syncrhonized boolean putIfAbsent(E x) {
 boolean absent = !list.contains(x);
if(absent) {
 list.add(x);
}
return absent;
}

O código acima tem o Aparência de ser thread-safe. No entanto, na realidade não é. Neste caso, o bloqueio é obtido no exemplo da classe. No entanto, é possível para o lista para ser modificado por outro thread não usando esse método. A abordagem correta seria usar

public boolean putIfAbsent(E x) {
 synchronized(list) {
  boolean absent = !list.contains(x);
  if(absent) {
    list.add(x);
  }
  return absent;
}
}

O código acima iria bloquear todos os tópicos tentando modificar lista de modificar a lista até que o bloco sincronizado foi concluída.

Como uma questão prática, a vantagem de métodos sincronizados mais blocos sincronizados é que eles são mais idiot-resistente; porque você não pode escolher um objeto arbitrário para bloquear, você não pode abusar da sintaxe método sincronizado a fazer coisas estúpidas como trancar em um literal string ou bloqueio do conteúdo de um campo mutável que se mudou para fora sob os fios.

Por outro lado, com métodos sincronizados você não pode proteger o bloqueio de ficar adquirida por qualquer segmento que pode obter uma referência para o objeto.

Então, usando sincronizado como um modificador em métodos é melhor para proteger seus vaca-orkers de ferir-se, ao usar blocos sincronizados em conjunto com bloqueio final privado objetos é melhor a proteger o seu próprio código da vaca-orkers.

De um resumo especificação Java: http://www.cs.cornell.edu/andru/javaspec/17 .doc.html

A declaração sincronizado (§14.17) calcula uma referência a um objecto; Em seguida, tenta executar uma ação de bloqueio no objeto e não faz prosseguir até que a ação de bloqueio foi concluída com êxito. ...

Um método sincronizado (§8.4.3.5) executa automaticamente uma acção de bloqueio quando é invocada; seu corpo não é executado até que a ação de bloqueio tem completado com sucesso. Se o método é um método de instância , ele bloqueia o bloqueio associado com o exemplo, para o qual foi invocado (Isto é, o objecto que será conhecido como este durante a execução de o corpo do método). Se o método é estático , ele bloqueia a fechamento associado com o objecto de classe que representa a classe em que o método é definido. ...

Com base nestas descrições, eu diria que a maioria das respostas anteriores estão corretas, e um método sincronizado pode ser particularmente útil para métodos estáticos, onde teriam que descobrir como obter o "objeto de classe que representa a classe em que o método foi definido. "

Edit: Eu pensava inicialmente estes eram citações da especificação Java real. Esclareceu que esta página é apenas um resumo / explicação da especificação

TLDR;. Nem usar o modificador synchronized nem a expressão synchronized(this){...} mas synchronized(myLock){...} onde myLock é um campo última instância segurando um objeto particular


A diferença entre usar o modificador synchronized na declaração de método ea expressão synchronized(..){ } no corpo do método é o seguinte:

  • O modificador synchronized especificado na assinatura do método
    1. é visível no JavaDoc gerado,
    2. é determinável de forma programática via reflexão ao testar modificador de um método para Modifier.SYNCHRONIZED ,
    3. exige menos digitação e recuo em comparação com synchronized(this) { .... }, e
    4. (dependendo do seu IDE) é visível na conclusão contorno e código de classe,
    5. usa o objeto this como bloqueio quando declarado no método não-estático ou a classe delimitador quando declarou em um método estático.
  • A expressão synchronized(...){...} permite
    1. para sincronizar somente a execução de partes do corpo de um método,
    2. para ser usado dentro de um construtor ou um ( estática ) bloco de inicialização,
    3. para escolher o objeto de bloqueio que controla o acesso sincronizado.

No entanto, utilizando o modificador de synchronized ou synchronized(...) {...} com this como o objeto de bloqueio (como em synchronized(this) {...}), tem a mesma desvantagem. Ambos uso o seu próprio exemplo como o objeto de bloqueio para sincronizar diante. Isso é perigoso porque não só o objeto em si, mas qualquer outro objeto externo / código que contém uma referência a esse objeto também pode usá-lo como um bloqueio de sincronização com efeitos colaterais potencialmente graves (degradação do desempenho e impasses ).

Portanto, a melhor prática é não usar o modificador synchronized nem a expressão synchronized(...) em conjunto com this como objeto de bloqueio, mas um objeto de bloqueio privada a este objeto. Por exemplo:

public class MyService {
    private final lock = new Object();

    public void doThis() {
       synchronized(lock) {
          // do code that requires synchronous execution
        }
    }

    public void doThat() {
       synchronized(lock) {
          // do code that requires synchronous execution
        }
    }
}

Você também pode usar vários objetos de bloqueio, mas necessidades de cuidados especiais a serem tomadas para garantir que isso não resultar em impasses quando usado aninhados.

public class MyService {
    private final lock1 = new Object();
    private final lock2 = new Object();

    public void doThis() {
       synchronized(lock1) {
          synchronized(lock2) {
              // code here is guaranteed not to be executes at the same time
              // as the synchronized code in doThat() and doMore().
          }
    }

    public void doThat() {
       synchronized(lock1) {
              // code here is guaranteed not to be executes at the same time
              // as the synchronized code in doThis().
              // doMore() may execute concurrently
        }
    }

    public void doMore() {
       synchronized(lock2) {
              // code here is guaranteed not to be executes at the same time
              // as the synchronized code in doThis().
              // doThat() may execute concurrently
        }
    }
}

Eu suponho que esta pergunta é sobre a diferença entre thread-safe Singleton e A inicialização lenta com check Duplo bloqueio . Eu sempre se referem a este artigo quando eu preciso implementar algumas singleton específico.

Bem, este é um thread-safe Singleton :

// Java program to create Thread Safe 
// Singleton class 
public class GFG  
{ 
  // private instance, so that it can be 
  // accessed by only by getInstance() method 
  private static GFG instance; 

  private GFG()  
  { 
    // private constructor 
  } 

 //synchronized method to control simultaneous access 
  synchronized public static GFG getInstance()  
  { 
    if (instance == null)  
    { 
      // if instance is null, initialize 
      instance = new GFG(); 
    } 
    return instance; 
  } 
} 

Pros:

  1. preguiçoso inicialização é possível.

  2. É thread-safe.

Contras:

  1. getInstance () é sincronizado de modo que faz com que o desempenho lento como múltiplos segmentos não é possível aceder ao mesmo simultaneamente.

Este é um preguiçoso inicialização com check Duplo bloqueio :

// Java code to explain double check locking 
public class GFG  
{ 
  // private instance, so that it can be 
  // accessed by only by getInstance() method 
  private static GFG instance; 

  private GFG()  
  { 
    // private constructor 
  } 

  public static GFG getInstance() 
  { 
    if (instance == null)  
    { 
      //synchronized block to remove overhead 
      synchronized (GFG.class) 
      { 
        if(instance==null) 
        { 
          // if instance is null, initialize 
          instance = new GFG(); 
        } 

      } 
    } 
    return instance; 
  } 
} 

Pros:

  1. preguiçoso inicialização é possível.

  2. Ele também é thread-safe.

  3. Desempenho reduzido por causa da palavra-chave sincronizado é superada.

Contras:

  1. Na primeira vez, ele pode afetar o desempenho.

  2. Como contras. do método de bloqueio dupla verificação é suportável por isso pode ser utilizado para aplicações de multi-threaded alto desempenho.

Por favor, consulte este artigo para obter mais detalhes:

https://www.geeksforgeeks.org/java- únicas-design-padrão-práticas-exemplos /

Sincronizar com threads. 1) Nunca use sincronizado (this) em um segmento que não funciona. Sincronizando com (este) usa o fio corrente como o objeto de segmento de bloqueio. Uma vez que cada linha é independente de outros tópicos, não há coordenação de sincronização. 2) Testes de código mostram que em Java 1.6 em um Mac a sincronização método não funciona. 3) sincronizado (lockObj) onde lockObj é um objeto comum compartilhada de todos os tópicos sincronização em que vai trabalhar. 4) ReenterantLock.lock () e .unlock de trabalho (). Veja tutoriais Java para isso.

O código a seguir mostra esses pontos. Ele também contém a Vector thread-safe que ser substituído para o ArrayList, para mostrar que muitos segmentos adicionando a um vetor não perder qualquer informação, enquanto o mesmo com um ArrayList pode perder informações. 0) atual mostra o código perda de informações devido a condições de corrida A) Comente a linha A rotulado atual e descomente a linha A acima dela, em seguida, executar, método perde dados, mas que não deveria. B) Um passo reverso, descomente B e // bloco final}. Em seguida, execute a ver resultados sem perda de dados C) Comentário fora B, descomente C. Run, consulte Sincronizando na (this) perde dados, como esperado. Não tem tempo para completar todas as variações, espero que isso ajude. Se a sincronização (esta), ou as obras de sincronização método, por favor estado que versão do Java e OS você testou. Obrigado.

import java.util.*;

/** RaceCondition - Shows that when multiple threads compete for resources 
     thread one may grab the resource expecting to update a particular 
     area but is removed from the CPU before finishing.  Thread one still 
     points to that resource.  Then thread two grabs that resource and 
     completes the update.  Then thread one gets to complete the update, 
     which over writes thread two's work.
     DEMO:  1) Run as is - see missing counts from race condition, Run severa times, values change  
            2) Uncomment "synchronized(countLock){ }" - see counts work
            Synchronized creates a lock on that block of code, no other threads can 
            execute code within a block that another thread has a lock.
        3) Comment ArrayList, unComment Vector - See no loss in collection
            Vectors work like ArrayList, but Vectors are "Thread Safe"
         May use this code as long as attribution to the author remains intact.
     /mf
*/ 

public class RaceCondition {
    private ArrayList<Integer> raceList = new ArrayList<Integer>(); // simple add(#)
//  private Vector<Integer> raceList = new Vector<Integer>(); // simple add(#)

    private String countLock="lock";    // Object use for locking the raceCount
    private int raceCount = 0;        // simple add 1 to this counter
    private int MAX = 10000;        // Do this 10,000 times
    private int NUM_THREADS = 100;    // Create 100 threads

    public static void main(String [] args) {
    new RaceCondition();
    }

    public RaceCondition() {
    ArrayList<Thread> arT = new ArrayList<Thread>();

    // Create thread objects, add them to an array list
    for( int i=0; i<NUM_THREADS; i++){
        Thread rt = new RaceThread( ); // i );
        arT.add( rt );
    }

    // Start all object at once.
    for( Thread rt : arT ){
        rt.start();
    }

    // Wait for all threads to finish before we can print totals created by threads
    for( int i=0; i<NUM_THREADS; i++){
        try { arT.get(i).join(); }
        catch( InterruptedException ie ) { System.out.println("Interrupted thread "+i); }
    }

    // All threads finished, print the summary information.
    // (Try to print this informaiton without the join loop above)
    System.out.printf("\nRace condition, should have %,d. Really have %,d in array, and count of %,d.\n",
                MAX*NUM_THREADS, raceList.size(), raceCount );
    System.out.printf("Array lost %,d. Count lost %,d\n",
             MAX*NUM_THREADS-raceList.size(), MAX*NUM_THREADS-raceCount );
    }   // end RaceCondition constructor



    class RaceThread extends Thread {
    public void run() {
        for ( int i=0; i<MAX; i++){
        try {
            update( i );        
        }    // These  catches show when one thread steps on another's values
        catch( ArrayIndexOutOfBoundsException ai ){ System.out.print("A"); }
        catch( OutOfMemoryError oome ) { System.out.print("O"); }
        }
    }

    // so we don't lose counts, need to synchronize on some object, not primitive
    // Created "countLock" to show how this can work.
    // Comment out the synchronized and ending {, see that we lose counts.

//    public synchronized void update(int i){   // use A
    public void update(int i){                  // remove this when adding A
//      synchronized(countLock){            // or B
//      synchronized(this){             // or C
        raceCount = raceCount + 1;
        raceList.add( i );      // use Vector  
//          }           // end block for B or C
    }   // end update

    }   // end RaceThread inner class


} // end RaceCondition outter class
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top