Guia Completo para Sincronização em Java
Publicados: 2022-05-20Antes de explicarmos a sincronização em Java , devemos revisitar brevemente o conceito de multithreading. O recurso multithreading do Java permite a execução simultânea de duas ou mais partes de um programa para utilização máxima da CPU. Cada parte de tal programa é um thread, e threads são processos leves dentro de um processo.
Agora, vários threads de um programa podem tentar acessar os mesmos recursos e produzir resultados imprecisos. Portanto, deve haver alguma sincronização para garantir que apenas um thread tenha acesso aos recursos em um determinado momento.
Este guia sobre o que é sincronização em Java explorará o conceito de sincronização em detalhes com exemplos.
O que é sincronização em Java?
A sincronização Java é a capacidade de controlar o acesso de vários threads a um recurso compartilhado. É útil quando programas Java multiencadeados tentam acessar o mesmo recurso e produzem resultados errôneos. Usando o recurso de sincronização Java, apenas um único encadeamento pode acessar o recurso em um determinado ponto de tempo.
Java fornece uma maneira de sincronizar a tarefa de threads usando blocos sincronizados que sincronizam no mesmo objeto e podem ter apenas um thread executando dentro deles por vez. Esses blocos são marcados com a palavra-chave sincronizada, bloqueando qualquer outra thread que tente entrar no bloco sincronizado até que a thread que já está dentro do bloco termine sua execução e saia do bloco.
A sintaxe para escrever um bloco sincronizado
A sintaxe geral para escrever um bloco sincronizado em Java é a seguinte:
sincronizado( lockObject )
{
// instruções sincronizadas
}
Na sintaxe acima, lockObject refere-se a um objeto cujo bloqueio está relacionado aos elementos sincronizados. Agora, isso nos leva ao conceito de bloqueio em Java.
Bloqueios em Java
A sincronização em Java é construída em torno do bloqueio ou monitor. Cada objeto tem um bloqueio associado. Idealmente, um thread que requer acesso aos campos de um objeto deve primeiro obter o bloqueio do objeto. O bloqueio é um mecanismo de sincronização de thread mais sofisticado e flexível do que o bloco de sincronização. Ele é definido dentro do pacote java.util.concurrent.lock contendo extensas implementações de bloqueio.
Aprenda cursos de desenvolvimento de software online das melhores universidades do mundo. Ganhe Programas PG Executivos, Programas de Certificado Avançado ou Programas de Mestrado para acelerar sua carreira.
Método Sincronizado Java
A finalidade de um método sincronizado Java é bloquear objetos para recursos compartilhados. Assim, quando as threads invocam um método sincronizado, o método automaticamente obtém o bloqueio para esse objeto e o libera assim que a thread executa seu trabalho.
Aqui está um exemplo de um método sincronizado Java:
//exemplo de método java sincronizado
classe Tabela{
void printTable(int n){//método sincronizado sincronizado
for(int i=1;i<=5;i++){
System.out.println(n*i);
tentar{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
}
}
}
class MyThread1 estende Thread{
Tábua;
MyThread1(Tabela t){
this.t=t;
}
public void executar(){
t.printTable(5);
}
}
class MyThread2 estende Thread{
Tábua;
MyThread2(Tabela t){
this.t=t;
}
public void executar(){
t.printTable(100);
}
}
classe pública TestSynchronization2{
public static void main(String args[]){
Table obj = new Table();//somente um objeto
MeuThread1 t1=novo MeuThread1(obj);
MeuThread2 t2=novo MeuThread2(obj);
t1.início();
t2.início();
}
}
Resultado:
5
10
15
20
25
100
200
300
400
500
O que acontece sem sincronização?
Agora, vamos ver o programa anterior sem sincronização (observe a ausência da palavra-chave sincronizada).
classe Tabela{
void printTable(int n){//método não sincronizado
for(int i=1;i<=5;i++){
System.out.println(n*i);
tentar{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
}
}
}
class MyThread1 estende Thread{
Tábua;
MyThread1(Tabela t){
this.t=t;
}
public void executar(){
t.printTable(5);
}
}
class MyThread2 estende Thread{
Tábua;
MyThread2(Tabela t){
this.t=t;
}
public void executar(){
t.printTable(100);
}
}
class TestSynchronization1{
public static void main(String args[]){
Table obj = new Table();//somente um objeto
MeuThread1 t1=novo MeuThread1(obj);
MeuThread2 t2=novo MeuThread2(obj);
t1.início();
t2.início();
}
}
Resultado:
5
100
10
200
15
300
20
400
25
500
Como você pode ver, a saída é inconsistente sem sincronização.
Explore nossos cursos populares de engenharia de software
SL. Não | Programas de Desenvolvimento de Software | |
1 | Mestre em Ciência da Computação pela LJMU & IIITB | Programa de Certificado de Segurança Cibernética Caltech CTME |
2 | Curso de Desenvolvimento Full Stack | Programa PG em Blockchain |
3 | Programa de Pós-Graduação Executiva em Desenvolvimento de Software - Especialização em DevOps | Veja todos os Cursos de Engenharia de Software |
Tipos de sincronização em Java
Para responder o que é sincronização de threads em Java , temos dois tipos de sincronização disponíveis: sincronização de threads e sincronização de processos.
Vamos entender o que cada um significa.
Sincronização de threads: quando vários threads tentam acessar um recurso compartilhado, devemos garantir que o recurso seja usado por apenas um thread por vez. A sincronização de threads é o processo de permitir que apenas um thread use o recurso compartilhado quando vários threads estão tentando usar o recurso simultaneamente.
Sincronização de processos: refere-se à execução simultânea de vários processos para atingir um estado em que os processos se comprometem com uma ordem de execução apropriada. A sincronização de processos é necessária quando dois ou mais processos cooperam e a execução de um processo afeta o outro. Assim, a sincronização de processos elimina a possibilidade de saídas imprecisas e garante a ordem de execução correta.
Métodos de sincronização em Java
Em termos gerais, existem quatro métodos de sincronização em Java:
- Métodos estáticos sincronizados
- Métodos de instância sincronizados
- Bloco sincronizado dentro de métodos estáticos
- Bloco sincronizado dentro de métodos de instância
Vejamos cada método de sincronização Java com mais detalhes.
Métodos estáticos sincronizados
Aqui, usamos a palavra-chave sincronizada para marcar os métodos estáticos em Java. Aqui está um exemplo de um método estático sincronizado Java:
public static MyStaticCounter {
contagem int estática privada = 0;
incremento nulo sincronizado estático público (valor int) {
contagem += valor;
}
}
Métodos de instância sincronizados
Ao usar um bloco sincronizado com métodos de instância, cada objeto tem seu método sincronizado. Cada objeto pode ter apenas um thread que pode ser executado dentro de um método. Se houver vários objetos, um único thread pode ser executado para cada objeto dentro do bloco.
classe pública MeuContador {
contagem de inteiros privados = 0;
incremento nulo sincronizado público (valor int) {
this.count += valor;
}
decremento void sincronizado público (valor int) {
this.count -= valor;
}
}
Bloco sincronizado dentro de métodos estáticos
Abaixo está um exemplo onde usamos um bloco sincronizado dentro de um método estático:
classe pública MinhaClasse {
public static void print(String message) {
sincronizado(MinhaClasse.classe) {
log.writeln(mensagem);
}
}
}
Bloco sincronizado dentro de métodos de instância
Em vez de sincronizar todo o método, podemos usar o sincronizado em um bloco específico dentro do método. Abaixo está um exemplo de um bloco de código sincronizado dentro de um método não sincronizado:
incremento void público (valor int) {
sincronizado(este) {
this.count += valor;
}
}
Necessidade de sincronização em Java
Agora que você sabe o que é sincronização em Java , você deve estar se perguntando por que nós a usamos em primeiro lugar.
A palavra-chave sincronizada do Java fornece funcionalidades essenciais para programação simultânea. Veja como a sincronização em Java ajuda:
- A sincronização Java fornece o recurso de bloqueio para eliminar qualquer condição de corrida entre os encadeamentos e garantir acesso mutuamente exclusivo ao recurso compartilhado.
- O bloqueio sincronizado Java fornece os recursos de bloqueio e desbloqueio. Portanto, um thread precisa adquirir o bloqueio antes de inserir um método ou bloco sincronizado.
- A palavra-chave sincronizada impede a reordenação de instruções de programa pelo compilador.
Conclusão
Resumindo, a sincronização em Java garante que apenas um thread possa acessar o recurso compartilhado por vez. Podemos sincronizar um bloco ou método usando a palavra-chave sincronizada do Java. Quando uma thread deseja entrar em um bloco sincronizado, ela deve adquirir um bloqueio e, após sair do bloco, a thread libera o bloqueio. Podemos usar a palavra-chave sincronizada com métodos ou dentro do bloco de um método.
Quer saber onde aprender Java?
Certificação PG vinculada ao trabalho do upGrad em Engenharia de Software é o que você procura!
Especialmente projetada para recém-formados e finalistas, a Certificação PG vinculada ao trabalho do upGrad em Engenharia de Software é perfeita para quem deseja aprender a programar e ser colocado em funções de software de nível básico. Este programa online de 5 meses ensinará as principais habilidades de software como Java, JavaScript, HTML5, DSA, AWS, MERN e muito mais!
P: Por que usamos sincronizado em Java?
R: A palavra-chave sincronizada em Java garante que apenas um encadeamento possa acessar os recursos compartilhados por vez. É útil quando programas Java multiencadeados tentam acessar o mesmo recurso e produzem resultados imprecisos.
P: Como a sincronização é implementada em Java?
R: Java implementa a sincronização usando o conceito de monitores com apenas um thread possuindo um monitor em um determinado momento. Quando um encadeamento adquire um bloqueio, ele obtém acesso ao monitor e todos os outros encadeamentos que tentam entrar no monitor bloqueado permanecem bloqueados até que o primeiro encadeamento deixe o monitor.
P: O que é um impasse em Java?
R: O deadlock Java ocorre quando um thread está aguardando um bloqueio de objeto, mas outro thread o adquire e o segundo thread está aguardando um bloqueio de objeto adquirido pelo primeiro. Assim, ambas as threads esperam uma pela outra liberar o bloqueio, resultando em um impasse.