0Pricing
Java Academy · Aula

ReadWriteLock em Cenários de Leitura e Escrita

Use ReadWriteLock para permitir leituras simultâneas e garantir escritas exclusivas em um cache.

ReadWriteLock em Cenários de Leitura e Escrita é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.

O problema dos leitores e escritores

Várias linhas de execução podem ler dados compartilhados com segurança simultaneamente. Porém, a escrita exige acesso exclusivo — não pode haver leituras ou escritas simultâneas. Um ReadWriteLock modela isso: vários leitores simultâneos OU um único escritor exclusivo.

import java.util.concurrent.locks.*;

ReadWriteLock rwLock = new ReentrantReadWriteLock();
Lock readLock  = rwLock.readLock();
Lock writeLock = rwLock.writeLock();

Bloqueio de leitura: acesso compartilhado

Várias linhas de execução podem manter o bloqueio de leitura simultaneamente, desde que nenhuma linha de execução mantenha o bloqueio de escrita:

class ReadableCache {
    private final Map<String, String> cache = new HashMap<>();
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    
    String get(String key) {
        lock.readLock().lock();
        try {
            return cache.get(key); // concurrent reads OK
        } finally {
            lock.readLock().unlock();
        }
    }
}

Bloqueio de escrita: acesso exclusivo

Apenas uma linha de execução pode manter o bloqueio de escrita por vez. Todos os leitores e os outros escritores ficam bloqueados durante uma escrita:

class WritableCache extends ReadableCache {
    private final ReadWriteLock wLock = new ReentrantReadWriteLock();
    private final Map<String, String> data = new HashMap<>();
    
    void put(String key, String value) {
        wLock.writeLock().lock();
        try {
            data.put(key, value); // exclusive write
        } finally {
            wLock.writeLock().unlock();
        }
    }
}

Exemplo completo de cache

Um cache seguro para uso por várias linhas de execução, no qual as leituras predominam e as escritas são raras:

class Cache<K,V> {
    private final Map<K,V> map = new HashMap<>();
    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    
    V get(K key) {
        lock.readLock().lock();
        try { return map.get(key); }
        finally { lock.readLock().unlock(); }
    }
    
    void put(K key, V value) {
        lock.writeLock().lock();
        try { map.put(key, value); }
        finally { lock.writeLock().unlock(); }
    }
    
    int size() {
        lock.readLock().lock();
        try { return map.size(); }
        finally { lock.readLock().unlock(); }
    }
}

Rebaixamento do bloqueio

ReadWriteLock permite rebaixar o bloqueio: adquira o bloqueio de escrita → adquira o bloqueio de leitura → libere o bloqueio de escrita. Isso permite que uma linha de execução passe de uma escrita exclusiva para uma leitura compartilhada sem liberar o bloqueio:

ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
Lock r = rwl.readLock(), w = rwl.writeLock();

w.lock(); // acquire write
try {
    // modify data
    r.lock(); // acquire read WHILE holding write
} finally {
    w.unlock(); // release write, now holding read only
}
try {
    // safely read the just-written data
} finally {
    r.unlock();
}

O bloqueio de leitura não pode ser promovido

A promoção do bloqueio (leitura → escrita) NÃO é compatível. Se uma linha de execução que mantém um bloqueio de leitura tentar adquirir o bloqueio de escrita, ocorrerá um deadlock, pois o bloqueio de escrita aguarda TODOS os leitores, incluindo a própria linha de execução:

// DEADLOCK: Do NOT do this
lock.readLock().lock();
try {
    lock.writeLock().lock(); // DEADLOCK — waits for readLock to release
} finally {
    lock.readLock().unlock();
}

Quando ReadWriteLock é útil

ReadWriteLock é vantajoso quando:

  • As leituras superam significativamente as escritas
  • As operações de leitura levam um tempo não trivial (por exemplo, consultas complexas)

Ele pode prejudicar o desempenho quando as escritas são frequentes (o bloqueio de escrita bloqueia todos os leitores) ou quando as operações são muito rápidas (devido ao custo adicional de dois objetos de bloqueio).

Comparando ReadWriteLock com synchronized

synchronized/ReentrantLock → apenas uma linha de execução por vez (até mesmo leitores simultâneos ficam bloqueados).
ReadWriteLock → vários leitores simultâneos e um escritor exclusivo. Oferece maior throughput de leitura em cenários com muitas leituras.

// synchronized: only one thread reads at a time
synchronized String get(String key) { return cache.get(key); }

// ReadWriteLock: many threads can read simultaneously
String get2(String key) {
    lock.readLock().lock();
    try { return cache.get(key); }
    finally { lock.readLock().unlock(); }
}

Considerações de desempenho

Adquirir e liberar dois objetos de bloqueio adiciona custo em comparação com um único bloqueio. Faça uma análise de desempenho antes de presumir que ReadWriteLock é mais rápido. Em cenários com muitas leituras e operações longas, o benefício é claro. Para cargas de trabalho rápidas com muitas escritas, um ReentrantLock simples pode ser mais rápido.

Alternativa: ConcurrentHashMap

Para operações simples de mapa, ConcurrentHashMap costuma ser mais rápido que um HashMap + ReadWriteLock, pois usa bloqueios internos no nível de segmento, sem contenção global:

// Often better than HashMap + ReadWriteLock for simple operations:
Map<String, String> concurrent = new ConcurrentHashMap<>();
concurrent.put("key", "value"); // thread-safe, no explicit lock
String v = concurrent.get("key"); // thread-safe

Equidade do bloqueio de leitura

Por padrão, ReentrantReadWriteLock não é justo (os leitores podem causar inanição dos escritores). Use o construtor justo para evitar a inanição dos escritores:

// Fair: waiting writers are served before new readers
ReentrantReadWriteLock fairLock = new ReentrantReadWriteLock(true);
System.out.println(fairLock.isFair()); // true

Verificação rápida

Em uma aplicação com muitas leituras, qual é a principal vantagem de ReadWriteLock em relação a um método synchronized simples?

Recapitulação: ReadWriteLock

Principais conclusões:

  • Várias leituras simultâneas OU uma única escrita exclusiva — nunca ambas
  • readLock.lock()/unlock() para leituras compartilhadas
  • writeLock.lock()/unlock() para escritas exclusivas
  • O rebaixamento do bloqueio é compatível; a promoção (leitura→escrita) causa deadlock
  • É ideal para muitas leituras com operações não triviais; use ConcurrentHashMap para mapas simples

Perguntas Frequentes

A aula “ReadWriteLock em Cenários de Leitura e Escrita” é grátis?

Sim — o texto completo de “ReadWriteLock em Cenários de Leitura e Escrita” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.

O que vou aprender em “ReadWriteLock em Cenários de Leitura e Escrita”?

Use ReadWriteLock para permitir leituras simultâneas e garantir escritas exclusivas em um cache. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Java Academy?

Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.

Quanto tempo leva a aula “ReadWriteLock em Cenários de Leitura e Escrita”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Java Academy?

Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. ReentrantLock versus synchronized
  2. ReadWriteLock em Cenários de Leitura e Escrita
  3. Variáveis Atômicas: Atualizações sem Bloqueios
  4. StampedLock e Leituras Otimistas
← Voltar para Java Academy