Concorrência na
API JAVA
Grupo: Angelo, Alyson, Felipe Silva, Leonardo, Luiz Claudio,Marcus e Paulo Sérgio
Introdução a concorrência em Java
TÓPICOS
Atomic Variables
Locks
Synchronizers (semaphores)
Concurrent Collections
ThreadPool
Executors
INTRODUÇÃO A
CONCORRÊNCIA EM JAVA
Exemplo clássico de um problema de sincronização
Modo tradicional de se resolver esse problema
Componente da API que resolve esse problema
PROBLEMA: SHARED COUNTER
PROBLEMA: SHARED COUNTER
PROBLEMA: SHARED COUNTER
OPERAÇÃO NÃO-ATÔMICA
Atômico = indivisível
counter++
1. Carregar valor da memória
2. Operar no valor
3. Gravar de volta na memória
OPERAÇÃO NÃO-ATÔMICA
CPU 1 + Thread 1 Main Memory CPU 2 + Thread 2
CPU Register Counter
count = 0 count = 0
CPU Register
count = 1 count = 1
count = 1
count = 2 count = 2
OPERAÇÃO NÃO-ATÔMICA
CPU 1 + Thread 1 Main Memory CPU 2 + Thread 2
CPU Register Counter CPU Register
count = 0 count = 0
count = 0
count = 1 count = 1
count = 1 count = 1
OPERAÇÃO NÃO-ATÔMICA
Condição de Corrida: Situação em que resultado da execução de
um programa depende da ordem em que as threads forem
executadas.
PROBLEMA: SHARED COUNTER
Problema: Duas threads duas threads realizando uma operação não atômica, o
que leva a um comportamento não esperado, por causa da condição de corrida
essa situação gera.
Solução tradicional: Marcar a região crítica com a palavra chave synchronized.
Monitor
Critical Area
Entry Set
Wait Set
Intrinsic Lock
Owner
ANALOGIA
ANALOGIA
ANALOGIA
ANALOGIA
ANALOGIA
ANALOGIA
ANALOGIA
ANALOGIA
ANALOGIA
ANALOGIA
Critical Area
Intrinsic Lock
Entry Set Wait Set
Thread
MONITOR E INTRINSIC LOCK
Monitor (em Java) é uma estrutura interna da JVM associada a cada objeto, usada
para coordenar o acesso concorrente a blocos ou métodos synchronized. Ele é
composto por dois elementos principais:
1.Intrinsic lock: mecanismo que controla a exclusão mútua, garantindo que
apenas uma thread por vez execute a seção crítica.
2.Condition Variables: permitem que threads esperem por certas condições antes
de prosseguir. Em Java, essas condições se manifestam como:
Entry Set: fila de threads que tentam adquirir o lock, mas ainda não
conseguiram entrar na seção crítica.
Wait Set: fila de threads que estavam na seção crítica, mas chamaram wait()
e aguardam uma notificação (notify() ou notifyAll()).
SYNCHRONIZED
CONCURRENCY API
De acordo com a documentação para API de concorrência em Java. As primitivas de
concorrência de baixo nível fornecidas pela linguagem Java (como synchronized, volatile,
wait(), notify() e notifyAll()) são difíceis de usar corretamente, e erros ao utilizar essas
funcionalidades podem ser difíceis de detectar e depurar.
As utilitárias de concorrência foram cuidadosamente auditadas para garantir que não
ocorram deadlock, starvation ou condições de corrida. Além de oferecer performance mais
alta.
JAVA.UTIL.CONCURRENT.ATOMIC
Uso de operação atômica a nível de hardware CompareAndSwap
Principais tipos de variáveis
AtomicInteger – para inteiros
AtomicLong – para longos
AtomicBoolean – para valores booleanos
AtomicReference<T> – para referências de objetos
Principais métodos
get() – lê o valor atual
set(value) – define um novo valor
incrementAndGet() / decrementAndGet() – incrementa/decrementa e retorna o novo
valor
getAndIncrement() / getAndDecrement() – incrementa/decrementa, mas retorna o
valor anterior
compareAndSet(expected, update) – atualiza o valor apenas se ele for igual ao
esperado (operação CAS)
JAVA.UTIL.CONCURRENT.ATOMIC
SOLUÇÃO COM ATOMIC
Locks
LOCKS NO JAVA
INTRODUÇÃO
O que é um Lock?
Interface do Java da biblioteca concurrent.locks
Mecanismo de controle de concorrência
Garantem acesso exclusivo a recursos compartilhados
Possui:
Mais flexibilidade que o Syncronized
LOCKS NO JAVA
INTRODUÇÃO
ReentrantLock
A implementação mais utilizada
Classe que implementa a interface Lock
LOCKS NO JAVA
INTRODUÇÃO
ReentrantLock - Principais características:
Reentrância.
Modo Justo.
Métodos úteis
Diagnóstico e controle
REENTRÂNCIA:
Múltiplas chamadas:
Uma mesma Thread pode chamar o
lock múltiplas vezes
Lock e unLock
Cada chamada a lock() deve ser
emparelhada com o unLock()
Pode causar erro de deadLock
unLock() deve tá dentro de um
Finally
CARACTERÍSTICAS
MODO JUSTO( FAIR )
Por padrão:
O lock não é “justo”, ou seja pode furar fila
Mas é possível tornar lock “justo” com:
Configurado:
Neste modo, a Thread que está esperando por mais tempo terá prioridade
Comportamento do tipo FIFO – First-In, First-Out.
CARACTERÍSTICAS
MÉTODOS ÚTEIS
Lock() e unLock() tryLock(timeout, uni)
Adquire e libera o lock Espera até um tempo limite. Ideal para evitar
deadlocks.
tryLock()
lockInterruptibly()
Tenta adquirir o lock sem esperar
Adquire o lock, mas permite que a thread
Retorna true se conseguir
seja interrompida enquanto espera.
CARACTERÍSTICAS
DIAGNÓSTICO E CONTROLE
isLocked()
verifica se o lock está sendo mantido
Verifica se o lock está atualmente bloqueado por alguma thread (não importa qual).
getHoldCount()
Verifica quantas vezes o lock foi adquirido
Útil para diagnosticar reentrância incrementando esse contador
CARACTERÍSTICAS
SYNCRONIZED X LOCK
Comparações rápidas
Quando usar oque
Use synchronized para casos simples
Use ReentrantLock se precisar das características
LOCKS NO JAVA
INTRODUÇÃO
ReentrantReadWriteLock
Controle fino de concorrência
Oque faz:
É uma implementação de lock que permite dois tipos de locks
Leitura ( ReadLock )
Escrita ( WriteLock )
READLOCK
COMO FUNCIONA
Múltiplas Threads podem ler ao
mesmo tempo
VANTAGEM
Permite melhor desempenho em
situações de pouca escrita e
muitas leituras do recurso
WRITELOCK
COMO FUNCIONA
Apenas uma thread pode
escrever e bloqueia todas as
outras ( Inclusive as de leitura )
REETRANTLOCK
Esse WriteLock se assemelha ao
reetrantLock
Semáforo
SEMÁFOROS NO JAVA
INTRODUÇÃO
Controle de acesso a recursos compartilhados por meio de permissões.
Príncipais features:
Permits;
Acquiring permits;
Releasing permits;
Fairness.
SEMÁFOROS NO JAVA
QUANDO USAR?
Situações onde é preciso limitar o número de acessos simultâneos à
recursos compartilhados, como:
Pools de recursos: número fixo de recursos, ex: bancos de dados;
Seções críticas;
Controle de fluxo em sistemas concorrentes.
SEMÁFOROS NO JAVA
ETAPAS DE USO
Criar uma instância de Semaphore
com a quantidade de permissões;
Obter permissões: uso do método
acquire();
Liberar permissões: método release();
Exemplo
Concurrent Collections
CONCURRENT COLLECTIONS
INTRODUÇÃO
O que é?
Conjunto de estruturas de dados especializadas
Permite a utilização de várias threads
Não precisa de sync externo
Altamente escalável e alta performance
CONCURRENT COLLECTIONS
VANTAGENS
Por que usar?
Melhor performance que wrappers sincronizados
Segurança para threads embutido
Operações atômicas
CONCURRENT COLLECTIONS
TIPOS
BlockingQueue
ConcurrentLinkedQueue
CopyOnWriteArrayList
PRÁTICA SUPERMERCADO
PADRÃO PRODUTOR-CONSUMIDOR
Thread Pool
THREAD POOL
O que é?
Um pool de threads é um conjunto de threads
que podem ser "reutilizadas" para executar
tarefas.
Permite a utilização de várias threads e
Controle sobre a quantidade de threads
simultâneas.
é uma alternativa à criação de uma nova
thread para cada tarefa que você precisa
executar.
THREAD POOL
VANTAGENS
Por que usar?
Melhor desempenho em comparação à criação
de threads individuais.
Controle sobre a quantidade de threads
simultâneas.
Redução do consumo de recursos e prevenção
de sobrecarga no sistema.
ENTENDENDO COMO FUNCIONA
THREAD POOL
COMO FUNCIONA
As tarefas são adicionadas a
uma fila de bloqueio. Quando
uma thread do pool está
ociosa, ela retira uma tarefa
da fila e a executa. As demais
threads aguardam na fila até
estarem disponíveis.
Exemplo
Executor
EXECUTOR
O que é ?
Execução assíncrona capaz de
executar tarefas simultaneamente
em segundo plano
Delegação de Tarefas
EXECUTOR
Diagrama Código
ExecutorService executorService = Executors.newFixedThreadPool(10);
EXECUTOR
POR QUE USAR
Por que usar?
Melhora o desempenho: A criação de uma nova thread para cada
tarefa pode ser custosa em termos de tempo e recursos.
Gerenciamento de recursos: Limitar o número de threads evita o
consumo excessivo de recursos do sistema (CPU, memória)
Controle do ciclo de vida das threads: O ExecutorService fornece
mecanismos para controlar o ciclo de vida das threads
Obrigado!!