Todo lugar que se prese a falar sobre modelos de threading, native x green, fala que não existe razão para ter threads implementadas em user-space, chamadas de green-threads, se o SO possuir uma boa implementação nativa. Bom, se olharmos em volta, como neste blog, nas listas de discussão do JikesRVM, do Ruby ou do JRockit da época de 2004, vamos notar que todos reclamam muito das limitações e problemas impostos pelo uso de green-threads. As falhas apontadas são tantas que cria uma duvida se existe alguma justa razão em usá-las.
Para entender melhor a situação, vejamos o modelo de execução que todo sistema operacional espera de seus processos. Um processo possui uma ou mais threads, cada thread possui apenas uma linha de execução* e faz chamadas bloqueantes ao kernel. Ou seja, cada uma deve seguir executando por apenas um caminho e deve parar enquanto uma chamada ao sistema não completa. Contrastemos agora com modelo de green-threads, que pode ser visto da seguinte forma: um processo possui uma ou mais threads, cada uma administra varias linhas de execução e uma chamada ao kernel não impede prosseguir com as demais.
Essa diferença de funcionamento gera dois problemas. Primeiro de identidade, já que cada thread não possui somente uma linha de execução associada, então primitivas de locking não funcionam pois duas green-thread vão aparecer para o kernel como uma só. O segundo está relacionado ao comportamento do kernel, uma chamada bloqueante partindo de uma linha de execução vai causar várias outras pararem junto.
Ambos problemas dificultam muito a integração com bibliotecas externas, que podem usar o mecanismo de locking do sistema operacional, ou então bloquear indevidamente demais threads. Por exemplo, no Gtk+, o acesso aos widgets é protegido por locks nativos, que em um ambiente com green-threads vai por água abaixo e acaba corrompendo o estado, também tem o fato que executar processamento pesado fora da thread de eventos não ajuda, pois se uma bloqueia, todas bloqueiam. Por fim, tem a questão da escalabilidade, já que várias threads são bloqueadas sem precisar.
Existem alguns sistemas que conseguiram transpor essas barreiras, mas não sem um alto custo associado. Passam, primeiro, a adotar uma primitiva de mais alto nível que uma thread, como um ator, que é muito mais simples de utilizar. Depois fazem o trabalho pesado, criam um mecanismo de execução assíncrona das tarefas bloqueantes, seja fazendo offload para threads nativas auxiliares, ou usando aio e/ou multiplexação. Por fim, partem para as medidas radicais, definindo uma interface para código estrangeiro que garante a semântica e o comportamento das green-threads.
A interface de integração com código estrangeiro, também conhecida por FFI (Foreign Function Interface), é o elemento mais crítico e problemático, pois precisa impor uma forma diferente de trabalho aos integradores, normalmente via troca assíncrona de mensagens entre uma thread com o código ‘perigoso’ e as demais gerenciadas. Uma versão muito mais cabeluda do JNI, para quem conhece.
Das linguagens que implementam efetivamente userland threading, que eu conheço são
Erlang, Scheme e Factor. Elas permitem o uso de milhares de thread leves que consomem poucos recursos e não fazem o escalonador do SO entrar em parafuso. A JVM da BEA, JRockit, uma época suportou green-threads, mas devido a dificuldade de implementar a parte GUI do Java e não criar caos durante chamadas nativas, desistiram do projeto quando o linux passou a ter suporte nativo descente.
* Por linha de execução entenda o conjunto de registradores e a pilha de funções.
2 responses so far ↓
1 Thiago Silva // Sep 7, 2007 at 3:31 am
Então, que conclusão você tira com este post? Green-threads são, de fato, mal implementadas, nas implementações citadas?
2 kumpera // Sep 14, 2007 at 9:27 am
Eu acho que o maior problema com green-threads é a interface com chamadas blocantes que é oferecida.
Erlang usa um esquema de ports que evita por completo esse problema, a um custo que escrever um wrapper para o stdio do C é muito mais dificil que com JNI.
No geral, algumas linguagens possuem sim boas implementações de green-threads. Mas definitivamente Java ou Ruby não entram nessa lista.
Leave a Comment