Artigo Java Magazine 11 - Concorrência e a JVM
Artigo publicado pela Java magazine.
Atenção: por essa edição ser muito antiga não há arquivo PDF para download.Os artigos dessa edição estão disponíveis somente através do formato HTML.
Concorrência e a JVM
Threads e programação concorrente em Java
Nos artigos "Performance em Java" (Edição 3) e "Garbage Collection" (Edição 5), analisamos como a JVM executa código (interpretador/compilador JIT) e como gerencia memória (com ênfase no Garbage Collector). O terceiro elemento fundamental da arquitetura da JVM é o suporte à Programação Concorrente, que veremos neste artigo.
Suporte nativo
Assim como o gerenciamento de memória, o suporte à programação concorrente não costuma fazer parte da maioria das linguagens tradicionais, tais como C/C++. Nestas, em geral o programador utiliza APIs do Sistema Operacional (SO) diretamente. Quando muito, pode haver bibliotecas que encapsulam as primitivas do SO, de forma a facilitar um pouco seu uso na linguagem – no Visual C++, por exemplo, classes da MFC como CMutex e CWinThread. Em Java essas funcionalidades são suportadas não só por APIs mas também pelo runtime (JRE) e pela linguagem, o que torna a programação concorrente muito mais fácil – além de portável.
Embora Java não tenha sido a primeira plataforma de desenvolvimento com suporte à programação concorrente, foi a primeira a tornar-se popular. Antes de Java só havia linguagens de pesquisa (como PROMELA) ou de nicho (como Erlang). Foi Java que introduziu a programação concorrente na rotina de muitos desenvolvedores anteriormente afastados pela complexidade e baixa portabilidade das alternativas disponíveis até então. Além disso, linguagens com suporte a concorrência anteriores a Java não eram modeladas em torno de threads, mas de outras primitivas, como processos e mecanismos de IPC (comunicação entre processos) otimizados para a programação concorrente. Outro fator que contribuiu foi a evolução dos sistemas operacionais, pois, no período em que Java apareceu, o recurso de multithreading, que poucos anos antes era raro em SOs de uso geral, tornou-se quase universal, e atualmente só não é encontrado em plataformas mais limitadas.
Threads
Java suporta a programação concorrente através de dois elementos fundamentais: o thread (java.lang.Thread) e o monitor. Este último é embutido no próprio layout de objetos Java, com API exposta por java.lang.Object – wait(), notify(), notifyAll() –, além de métodos ou blocos synchronized, que são “açúcar sintático” para funções do mesmo monitor. Em termos gerais, threads são subdivisões de um processo do SO que compartilham o mesmo espaço de endereçamento e outros recursos (como descritores de arquivos[1]), mas possuem um estado de execução[2] particular, podendo rodar em paralelo se houver várias CPUs, ou dividir o tempo de uma CPU.
O compartilhamento de memória torna threads mais leves que processos, e a comunicação entre threads – geralmente feita via variáveis compartilhadas – é mais eficiente que qualquer outro mecanismo de IPC. Pelo mesmo motivo (a ausência de proteção de memória), a programação com threads costumava ser pouco robusta: um crash ou uma corrupção de memória gerada por um thread afetaria todos os demais threads do mesmo processo.
Esse é outro motivo pelo qual a programação com threads se tornou mais popular com Java. Graças ao modelo de memória seguro, em Java é impossível (salvo bugs da JVM!) um thread mal-comportado afetar os demais desta forma. Na pior das hipóteses, um thread com bugs graves poderá induzir outros threads a deadlocks[3] e outros problemas algorítmicos. Mas até nesses casos, a JVM pode isolar grupos de threads que devem estar fortemente acoplados, de outros que não devem. Isso é um benefício adicional dos class loaders: em um container de Servlets, por exemplo, mesmo os piores bugs de uma aplicação web não conseguirão causar problemas em outra aplicação no mesmo processo, pois o container carrega os Servlets de cada contexto usando um class loader distinto, impedindo acesso indevido aos objetos de outras web-apps (o mesmo vale para aplicações corporativas hospedadas em servidores J2EE).
A implementação de threads e monitores pela JVM traz independência do sistema operacional, e aqui, como em outros casos, existem vantagens e desvantagens:
·Alguns recursos suportados pelos threads nativos podem não estar disponíveis em Java. Por exemplo, não podemos criar fiber threads[4] como na Win32. Por outro lado, alguns SOs têm capacidade nativa de threads inferior à oferecida por Java, ou mesmo nenhum suporte, sendo esses recursos totalmente implementados pela JVM. Um exemplo disso seria o PalmOS, cujos recursos de multitarefa são restritos – e os de multithreading, inexistentes (isso deve mudar no PalmOS 6.0, que deve estar disponível quando você ler este artigo)."
[...] continue lendo...Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Artigo