Sincronização em Java: o quê, como e por quê?



Este artigo sobre sincronização em Java o ajudará a orientar seu caminho para aprender sobre a sincronização de programas multithread.

Programas multi-threaded podem regularmente surgir com uma circunstância onde vários tentativa de obter o mesmo recurso que produz resultados fraudulentos e surpreendentes. Isso pode ser resolvido usando a sincronização em Java. Apenas um único thread específico pode chegar ao recurso em um determinado momento. Este artigo o ajudará a se familiarizar com a estratégia de sincronização.

Discutirei os tópicos nesta ordem:





Vamos começar!

Por que usar a sincronização em Java?



Se você iniciar com pelo menos dois threads dentro de um programa, pode haver uma chance de que vários threads tentem obter o mesmo recurso. Ele pode até mesmo criar um resultado inesperado devido a problemas de simultaneidade.

Sintaxe :

synchronized (objectidentifier) ​​{// Acessar variáveis ​​compartilhadas e outros recursos compartilhados}

Por exemplo, tentativa de escrever dentro de um arquivo equivalente. Isso pode corromper os dados, pois um dos threads pode sobrescrever os dados ou quando um thread está abrindo omesmo arquivo ao mesmo tempo, outro thread pode estar fechando o mesmo arquivo.É necessário sincronizar a ação de vários threads. Isso pode ser implementado usando um conceito chamado M onitores .



  • Cada está associado a um monitor, que um thread pode bloquear ou desbloquear.
  • Apenas um tópico de cada vez pode travar um monitor.
  • Java linguagem de programação fornece uma maneira muito útil de criar threads e sincronizar suas tarefas usando o Sincronizado blocos.
  • Ele também mantém os recursos compartilhados dentro deste bloco específico.

Blocos sincronizados em Java são marcados com o Sincronizado palavra-chave. Este bloco em Java está sincronizado em algum objeto.Todos os blocos sincronizados no mesmo objeto só podem ter um thread em execução dentro deles por vez. Todos os outros threads que tentam entrar no bloco sincronizado são bloqueados até que o thread dentro do bloco sincronizado saia do bloco.

Tipos de Sincronização

Existem basicamente dois tipos de sincronização disponíveis. Eles são:

  1. Sincronização de processos: A execução simultânea de vários threads ou processos para atingir um estado em que se comprometam com uma determinada sequência de ações.
  2. Sincronização de thread: Às vezes, quando mais de um tópicotenta acessar um recurso compartilhado, você precisa garantir que o recurso será usado por apenas um thread emum tempo.

Não vamos entrar em detalhes sobre esses tipos e tentar entender o que é .

Locks em Java

Como mencionei anteriormente, a sincronização é construída em torno de uma entidade interna conhecida como fechadura ou monitor . Cada objeto tem um cadeado associado a ele. Portanto, um thread que precisa de acesso consistente aos campos de um objeto precisa adquirir o bloqueio do objeto antes de acessá-los e, em seguida, liberar o bloqueio quando o trabalho estiver concluído.

No Java 5, o pacote java.util.concurrent.locks contém muitas implementações de bloqueio.

É assim que um cadeado se parece:

public class Lock {private boolean isLocked = false public synchronized void lock () lança InterruptedException {while (isLocked) {wait ()} isLocked = true} public synchronized void unlock () {isLocked = false notificar ()}}

O método lock () bloqueia a instância de Lock para que todos os threads que chamam lock () sejam bloqueados até que unlock () seja executado.

Multi-threading sem sincronização

Aqui está um exemplo simples que imprime o valor do contador em uma sequência e cada vez que o executamos, ele produz um resultado diferente com base na disponibilidade da CPU para um thread. Veja isso!

class Multithread {public void printCount () {try {for (int i = 5 i<0 i--) { System.out.println('Counter --- ' + i ) } } catch (Exception e) { System.out.println('Thread interrupted.') } } } class Thread extends Multithread { private Thread t private String threadName Multithread MT Thread( String name, Multithread mt) { threadName = name MT= mt } public void run() { MT.printCount() System.out.println('Thread ' + threadName + ' exiting.') } public void start () { System.out.println('Starting ' + threadName ) if (t == null) { t = new Thread (this, threadName) t.start () } } } public class TestThread { public static void main(String args[]) { Multithread MT = new Multithread() Thread t = new Thread( 'Thread - 1 ', MT) Thread t1 = new Thread( 'Thread - 2 ', MT) t.start() t1.start() // wait for threads to end try { t.join() t1.join() } catch ( Exception e) { System.out.println('Interrupted') } } }

Os resultados do programa acima são:

Saída- Sincronização em Java- Edureka

Multi-threading com sincronização

Este é o mesmo exemplo acima, mas imprime o valor do contador na sequência. Cada vez que o executamos, ele produz o mesmo resultado.

class Multithread {public void printCount () {try {for (int i = 5 i> 0 i--) {System.out.println ('Contador ---' + i)}} catch (Exception e) {System. out.println ('Thread interrompido.')}}} class Thread extends Multithread {private Thread t private String threadName Multithread MT Thread (String name, Multithread mt) {threadName = name MT = mt} public void run () {synchronized ( MT) {MT.printCount ()} System.out.println ('Thread' + threadName + 'exiting.')} Public void start () {System.out.println ('Iniciando' + threadName) if (t == null) {t = new Thread (this, threadName) t.start ()}}} public class TestThread {public static void main (String args []) {Multithread MT = new Multithread () Thread T = new Thread ('Thread - 1 ', MT) Thread T1 = new Thread (' Thread - 2 ', MT) T.start () T1.start () // esperar que os threads terminem tente {T.join () T1.join ()} catch (Exception e) {System.out.println ('Interrupted')}}}

A saída é descrita abaixo:

Palavra-chave sincronizada

como criar um conjunto

palavra-chave sincronizada marca um bloco ou um método uma seção crítica. Uma seção crítica é onde apenas um thread está executando por vez, e o thread mantém o bloqueio para a seção sincronizada. este sincronizado palavra-chave ajuda na escrita concorrente partes de qualquer aplicativo. Ele também protege os recursos compartilhados dentro do bloco.

A palavra-chave sincronizada pode ser usada com:

Vamos discutir o bloco de código.

Palavra-chave sincronizada: um bloco de código

Sintaxe

A sintaxe geral para escrever um bloco sincronizado é:

synchronized (lockObject) {// instruções sincronizadas}

Quando um thread deseja executar as instruções sincronizadas dentro do bloco, ele deve adquirir o bloqueio no monitor do lockObject. Apenas um thread pode adquirir o monitor de um objeto de bloqueio por vez. Portanto, todas as outras threads devem esperar até que a thread atualmente em execução adquira o bloqueio e conclua sua execução.
Assim, o sincronizado A palavra-chave garante que apenas um encadeamento executará as instruções do bloco sincronizado por vez e, portanto, evita que vários encadeamentos corrompam os dados compartilhados presentes no bloco.

Nota :

  • Se um tópico for colocado em espera (usando dormir() método), então ele não libera o bloqueio. Durante esse tempo de hibernação, nenhum thread estará executando as instruções de bloco sincronizado.
  • A sincronização Java vai lançar Null Pointer Exception se objeto de bloqueio usado em ' sincronizado (bloqueio) ' é nulo.

Agora, vamos discutir o método.

Palavra-chave sincronizada: Um método

Sintaxe

A sintaxe geral para escrever um método sincronizado é:

método sincronizado (parâmetros) {// código sincronizado}

Aqui lockObject é apenas uma referência a um objeto cujo bloqueio está associado ao monitor que representa as instruções sincronizadas.

Semelhante ao bloco sincronizado, um thread deve adquirir o bloqueio no objeto de monitor conectado com o método sincronizado. No caso do método sincronizado, o objeto de bloqueio é:

  • Objeto ‘.class’ - se o método fornecido for estático .
  • 'Este' objeto - se o método for não estático . ‘This’ é a referência ao objeto atual no qual o método sincronizado é invocado.

A palavra-chave sincronizada Java é reentrante na natureza. Isso significa que se um método sincronizado chama outro método sincronizado que requer o mesmo bloqueio, então o thread atual que está segurando o bloqueio pode entrar naquele método sem adquirir o bloqueio.

Vamos avançar para o tópico final deste artigo e apontar as principais diferenças entre a palavra-chave synchronized e o bloco de sincronização.

Diferença entre palavra-chave sincronizada e bloco sincronizado

  • Quando você usa uma palavra-chave sincronizada com um método , ele obtém um bloqueio no objeto para todo o método. Isso significa que nenhum outro encadeamento pode usar qualquer método sincronizado até que o encadeamento atual que é chamado tenha concluído sua execução.
  • Sincronizado quadra adquire um bloqueio no objeto apenas entre parênteses após a palavra-chave synchronized ser especificada. Isso significa que nenhum outro thread pode adquirir um bloqueio no objeto já bloqueado até que o bloco saia. Mas outras threads poderão acessar o resto do código que está presente no método.

Isso nos leva ao final deste artigo, onde discutimos como exatamente a sincronização em Java funciona. Espero que você tenha esclarecido tudo o que foi compartilhado com você neste tutorial.

Confira o pela Edureka, uma empresa de aprendizagem online confiável com uma rede de mais de 250.000 alunos satisfeitos espalhados por todo o mundo. Estamos aqui para ajudá-lo em todas as etapas de sua jornada, para nos tornarmos, além dessas perguntas da entrevista java, um currículo que é projetado para estudantes e profissionais que desejam ser um desenvolvedor Java.

Tem alguma questão para nós? Mencione isso na seção de comentários deste “Sincronização em Java ' artigo e entraremos em contato com você o mais breve possível.