A criação do encadeamento Java é cara porque há bastante trabalho envolvido:
- Um grande bloco de memória deve ser alocado e inicializado para a pilha de encadeamentos.
- É necessário fazer chamadas do sistema para criar / registrar o encadeamento nativo no sistema operacional host.
- Os descritores precisam ser criados, inicializados e adicionados às estruturas de dados internas da JVM.
Também é caro, no sentido de que o encadeamento amarra recursos enquanto estiver vivo; por exemplo, a pilha de encadeamentos, quaisquer objetos acessíveis a partir da pilha, os descritores de encadeamentos da JVM, os descritores de encadeamentos nativos do SO.
Os custos de todas essas coisas são específicos da plataforma, mas não são baratos em nenhuma plataforma Java que eu já tenha encontrado.
Uma pesquisa no Google me encontrou um antigo benchmark que relata uma taxa de criação de threads de ~ 4000 por segundo em um Sun Java 1.4.1 em um Xeon de dois processadores antigos de 2002, executando o Linux antigo de 2002. Uma plataforma mais moderna dará números melhores ... e não posso comentar sobre a metodologia ... mas pelo menos fornece uma estimativa de quanto a criação de encadeamentos provavelmente será cara .
Os testes comparativos de Peter Lawrey indicam que a criação de encadeamentos é significativamente mais rápida atualmente em termos absolutos, mas não está claro quanto disso se deve a melhorias no Java e / ou no sistema operacional ... ou em velocidades mais altas do processador. Mas seus números ainda indicam uma melhoria de mais de 150 vezes se você usar um pool de threads em vez de criar / iniciar um novo thread a cada vez. (E ele afirma que tudo isso é relativo ...)
(O exemplo acima pressupõe "encadeamentos nativos" em vez de "encadeamentos verdes", mas todas as JVMs modernas usam encadeamentos nativos por motivos de desempenho. Encadeamentos verdes são possivelmente mais baratos de criar, mas você paga por ele em outras áreas.)
Pesquisei um pouco para ver como a pilha de um encadeamento Java realmente é alocada. No caso do OpenJDK 6 no Linux, a pilha de encadeamentos é alocada pela chamada para pthread_create
criar o encadeamento nativo. (A JVM não passa pthread_create
uma pilha pré-alocada.)
Em seguida, na pthread_create
pilha é alocado por uma chamada da mmap
seguinte maneira:
mmap(0, attr.__stacksize,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
De acordo com man mmap
, o MAP_ANONYMOUS
sinalizador faz com que a memória seja inicializada em zero.
Portanto, mesmo que não seja essencial que as novas pilhas de encadeamentos Java sejam zeradas (conforme a especificação da JVM), na prática (pelo menos com o OpenJDK 6 no Linux) elas são zeradas.