O artigo apresenta como instruções simples e compactas podem não ser thread-safe e as opções que temos, dependendo do cenário, para resolver este problema: o uso dos locks ou dos tipos atômicos. Após isso, a arquitetura dos tipos atômicos é apresentada em maiores detalhes, bem como os benefícios de seu uso comparados ao uso de locks.
Em que situação o tema útil:
O uso de tipos atômicos apresenta uma opção mais leve que o uso de locks e pode ser a melhor escolha para cenários mais simples, envolvendo somente uma variável como, por exemplo, substituir o operador ++ (ou seus equivalentes) para cenários de execuções concorrentes do incremento.
Resumo DevMan:
Instruções compactas podem parecer thread-safe quando na verdade não são, como é o caso do uso do operador de incremento (++). Ao realizar o incremento de um valor sob acessos concorrentes, notamos inconsistências e duplicidade nos valores recebidos como resultado. Para resolver este problema temos duas opções: o uso de locks ou o uso de tipos atômicos. Vemos que o uso de locks, apesar de mandatório na maioria dos casos, pode ser evitado para cenários simples como este, por meio do uso de tipos atômicos que provêm garantia de proteção a acessos concorrentes sem o mesmo overhead imposto pelo uso de locks.
O termo “código Java multi-thread” não está mais vinculado a aplicações complexas, restritas a um grupo seleto de desenvolvedores lidando com threads, locks e similares. O dia-a-dia da maioria dos desenvolvedores já está repleto de situações nas quais suas classes podem ser acessadas por múltiplas threads ao mesmo tempo, mesmo que você nunca tenha escrito um trecho de código envolvendo uma Thread sequer. O entendimento de como o código irá se comportar em tais situações é essencial, mesmo que você desenvolva aplicações mais “tradicionais”. Neste contexto, este artigo fornece informações úteis para quem deseja escrever código Java multi-thread de forma correta, tirando benefício dos tipos atômicos introduzidos na versão 5.0 da linguagem.
As múltiplas threads já estão aí
A programação concorrente já é uma realidade. Independente da arquitetura ou camada de sua aplicação Java, certamente existe alguma forma de acesso concorrente ou, se não existe, é porque alguém já se preocupou com isso por você. Dois exemplos interessantes, um em cada extremo, em relação ao desafio da programação concorrente, são os Servlets e os EJBs.
Na arquitetura dos Servlets, uma única instância é acessada de forma concorrente. Múltiplas threads acessam o mesmo objeto ao mesmo tempo. Isso quer dizer que sua aplicação é responsável por gerenciar o acesso concorrente a elementos compartilhados, principalmente no que se refere às propriedades da classe. As variáveis criadas internamente nos métodos são locais às threads e não é necessário se preocupar com elas.
O caso dos EJBs é o oposto. Existe a garantia que somente uma thread por vez acessa uma instância do EJB ao mesmo tempo (exceto para o caso de um EJB Singleton, no qual o acesso concorrente é permitido). Para garantir a performance, são criadas várias instâncias, o que é chamado de ...