Sobes.tech
Middle

Que métodos de combate à condição de corrida de threads, além do uso da palavra-chave volatile, conhece?

sobes.tech IA

Resposta da IA

Existem várias abordagens principais para sincronização de threads e prevenção de condições de corrida no Android, além de volatile.

  1. Uso de synchronized: Bloqueia o acesso ao código ou método para outros threads até que o thread atual termine.

    // Método sincronizado
    synchronized void incrementCounter() {
        counter++;
    }
    
    // Bloco sincronizado
    void updateData() {
        synchronized (this) { // ou outro objeto monitor
            // código que requer sincronização
        }
    }
    
  2. Uso de classes do pacote java.util.concurrent.locks: Oferecem mecanismos de bloqueio mais flexíveis que synchronized.

    import java.util.concurrent.locks.ReentrantLock;
    
    private final ReentrantLock lock = new ReentrantLock();
    
    void performLockedOperation() {
        lock.lock(); // Aquisição do bloqueio
        try {
            // Código protegido pelo bloqueio
        } finally {
            lock.unlock(); // Liberação do bloqueio (importante no finally)
        }
    }
    
  3. Uso de classes do pacote java.util.concurrent.atomic: Fornecem operações atômicas que são executadas como uma única unidade sem interrupções por outros threads. Adequadas para operações simples sobre tipos primitivos e referências.

    import java.util.concurrent.atomic.AtomicInteger;
    
    private final AtomicInteger atomicCounter = new AtomicInteger(0);
    
    void incrementAtomicCounter() {
        atomicCounter.incrementAndGet(); // Incremento atômico
    }
    
  4. Uso de coleções seguras para threads: Coleções do pacote java.util.concurrent (por exemplo, ConcurrentHashMap, CopyOnWriteArrayList) projetadas para uso seguro em ambientes multithread sem sincronização explícita pelo desenvolvedor.

    import java.util.concurrent.ConcurrentHashMap;
    import java.util.Map;
    
    private final Map<String, Integer> concurrentMap = new ConcurrentHashMap<>();
    
    void updateMap(String key, Integer value) {
        concurrentMap.put(key, value); // operação segura de escrita
    }
    
  5. **Uso de **ThreadLocal**: Permite criar uma variável que terá uma cópia separada para cada thread. Assim, cada thread trabalha com sua própria cópia de dados, evitando a corrida.

    private final ThreadLocal<Integer> threadLocalValue = new ThreadLocal<Integer>() {
        @Override
        protected Integer initialValue() {
            return 0; // Valor inicial para cada thread
        }
    };
    
    void processData() {
        int value = threadLocalValue.get();
        value++;
        threadLocalValue.set(value); // Definir valor para o thread atual
    }
    

A escolha do método depende da natureza da tarefa, da necessidade de bloqueio, do tipo de dados e do desempenho requerido.