Middle
Quais são os métodos básicos de sincronização em Java?
sobes.tech IA
Resposta da IA
Formas básicas de sincronização em Java:
-
Palavra-chave
synchronized:- Usada para sincronizar métodos ou blocos de código.
- Um método marcado como
synchronizedbloqueia o acesso à instância do objeto para outros métodos sincronizados dessa mesma instância. synchronized (this): sincronização na instância atual do objeto.synchronized (ClassName.class): sincronização ao nível da classe, bloqueia o acesso para todos os threads que trabalham com essa classe.synchronized (object): sincronização em um monitor de objeto específico.
class Counter { private int count = 0; // Método sincronizado public synchronized void increment() { count++; } public void decrement() { // Bloco sincronizado synchronized (this) { count--; } } } -
Palavra-chave
volatile:- Garante a visibilidade das mudanças na variável entre threads.
- Não garante a atomicidade de operações complexas (por exemplo,
i++), apenas leitura e escrita. - Aplica-se a campos da classe.
class SharedData { volatile boolean flag = false; public void setFlag(boolean value) { flag = value; // A mudança na flag torna-se visível para outros threads } public boolean getFlag() { return flag; } } -
Bloqueios explícitos (Locks explícitos):
- Oferecem um controle mais flexível em comparação com
synchronized. - Interface
Locke suas implementações, comoReentrantLock. - Permitem escolher entre modo justo e injusto de bloqueio, obter o estado do bloqueio, interromper o thread durante a espera pelo bloqueio.
- Requerem chamadas explícitas a
lock()eunlock(). É importante usar um blocofinallypara chamarunlock().
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class Resource { private final Lock lock = new ReentrantLock(); public void performAction() { lock.lock(); // Aquisição do bloqueio try { // Seção crítica System.out.println(Thread.currentThread().getName() + " adquiriu o lock"); Thread.sleep(100); // Simulação de trabalho } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { lock.unlock(); // Liberação do bloqueio System.out.println(Thread.currentThread().getName() + " liberou o lock"); } } } - Oferecem um controle mais flexível em comparação com
-
wait(),notify(),notifyAll():- Métodos da classe
Object, usados para interação entre threads que aguardam a liberação do monitor. wait(): libera o monitor e coloca o thread em estado de espera até quenotify()ounotifyAll()seja chamado.notify(): acorda um thread que espera nesse monitor.notifyAll(): acorda todos os threads que aguardam nesse monitor.- Devem ser chamados dentro de um bloco ou método sincronizado no mesmo objeto monitor.
class ProducerConsumer { private final Object monitor = new Object(); private boolean isProduced = false; public void produce() throws InterruptedException { synchronized (monitor) { while (isProduced) { monitor.wait(); // Espera até que o consumidor consuma } // Produz System.out.println("Produzido"); isProduced = true; monitor.notifyAll(); // Notifica os consumidores } } public void consume() throws InterruptedException { synchronized (monitor) { while (!isProduced) { monitor.wait(); // Espera até que o produtor produza } // Consome System.out.println("Consumido"); isProduced = false; monitor.notifyAll(); // Notifica os produtores } } } - Métodos da classe
Estes mecanismos são a base para criar código multithread seguro em Java. A escolha de um método específico depende da natureza da tarefa e do nível de controle necessário sobre a sincronização.