Documente Academic
Documente Profesional
Documente Cultură
Aprofundando o conhecimento
No texto a seguir, extrado do Captulo 4, Conceitos de threads, da terceira edio
do livro Sistemas operacionais, de Deitel, Deitel e Choffnes (2005, p. 90109), o autor
explica mais detalhadamente o que um thread e mostra o funcionamento dos thre
ads em diversos sistemas operacionais. Leia e aprofunde seu conhecimento.
Processo pesado
Threads
novas requisies medida que elas chegam. Esses threads no so destrudos aps
atender requisio; ao contrrio, voltam ao conjunto e so novamente designados
para requisies que esto entrando.
Processadores de texto usam threads para aumentar a produtividade do usu
rio e melhorar a interatividade. Cada vez que o usurio digita um caractere no
teclado, o sistema operacional recebe uma interrupo de teclado e emite um sinal
para o processador de texto. Esse responde armazenando o caractere na memria
e exibindo-o na tela. Como os computadores atuais podem executar centenas
de milhes de instrues de processador entre digitaes sucessivas, processa
dores de texto podem executar diversos outros threads entre as interrupes do
teclado. Por exemplo, muitos dos processadores de hoje detectam erros de grafia
nas palavras medida que so digitadas e salvam periodicamente uma cpia do
documento para um disco para evitar perda de dados. Cada caracterstica imple
mentada com um thread separado consequentemente, o processador de texto
pode responder s interrupes do teclado mesmo que um ou mais de seus threads
estejam bloqueados devido a uma operao de E/S (por exemplo, salvar uma cpia
do arquivo em disco).
nascido
Iniciar
pronto
em execuo
Um processo
Thread
Espao
do usurio
Contexto
Todos os threads de
de um processo execuo
mapeiam para um
nico contexto
de execuo Espao
do ncleo
thread de controle. Por exemplo, threads de usurio no escalam bem para sistemas
multiprocessadores, porque o ncleo no pode despachar os threads de um processo
para mltiplos processadores simultaneamente, portanto, threads de usurio podem
resultar em desempenho abaixo do timo em sistemas multiprocessadores.16 Em um
mapeamento de threads muitos-para-um, todo o processo fica bloqueado quando
algum de seus threads requisita uma operao bloqueante de E/S, pois o processo
multithread inteiro o nico thread de controle que o sistema operacional reconhece.
Mesmo que o processo multithread contenha threads no estado pronto, nenhum de
seus threads pode executar at que o thread bloqueado passe para pronto, o que
pode fazer que o progresso da execuo se arraste no caso de processos multithread
que bloqueiam frequentemente. Aps o bloqueio de um thread de usurio, o ncleo
despachar um outro processo que pode conter threads de prioridade mais baixa
do que a dos threads prontos contidos no processo bloqueado. Por conseguinte,
threads de usurio tambm no suportam escalonamento de prioridades no mbito
do sistema, o que pode ser particularmente prejudicial para processos multithread
de tempo real.17 Note que algumas bibliotecas de suporte a threads traduzem cha
madas bloqueantes ao sistema para chamadas no bloqueantes para enfrentar esse
problema.18
Um processo
Thread
Espao
do usurio Contexto
de
execuo
Cada thread
de usurio Espao
mapeia do ncleo
para um
contexto
Thread
T1 T2 T3 T4 T1 T2 T3 T1 T2
Contexto
Espao
de
do usurio
Cada thread de execuo
ncleo pode
mapear para um
ou mais threads
de usurio
Espao
do ncleo
Web e sistemas de banco de dados criam com frequncia um thread para responder
a cada requisio de servio que chega. O reservatrio de threads permite que os
threads de ncleo continuem no sistema depois que um thread de usurio morra.
Ento o thread de ncleo pode ser alocado a um novo thread de usurio que criado
mais tarde. Isso melhora os tempos de resposta do sistema em ambientes como o
de servidores Web, porque as requisies podem ser designadas para threads que
j existam no reservatrio. Esses threads de ncleo persistentes so denominados
threadsoperrios, pois executam, tipicamente, diversas funes diferentes, depen
dendo dos threads a eles designados.25
Uma vantagem do mapeamento de thread muitos-para-um que as aplicaes
podem melhorar seu desempenho personalizando o algoritmo de escalonamento
da biblioteca de suporte a threads. Todavia, se um nico thread de usurio ficar
bloqueado, o sistema operacional bloqueia todo o processo multithread. Uma outra
limitao do mapeamento de threads muitos-para-um que os threads de um pro
cesso no podem executar simultaneamente em processadores mltiplos. Ativaes
de escalonador tentam resolver essas limitaes dos threads de usurio. Uma ativao
de escalonador um thread de ncleo que pode notificar eventos a uma biblioteca
de suporte a threads de nvel de usurio (por exemplo, um thread bloqueou ou um
processador est disponvel). Esse tipo de thread de ncleo denominado ativao
de escalonador, porque a biblioteca de suporte a threads de usurio pode executar
operaes de escalonamento de thread quando ativada por uma notificao de
evento s vezes denominada upcall.
Quando um processo multithread gerado, o sistema operacional cria uma
ativao de escalonador que executa o cdigo de inicializao da biblioteca de su
porte a threads de usurio do processo, que cria threads e requisita processadores
adicionais para seus threads se necessrio. O sistema operacional cria uma ativao
de escalonador adicional para cada processador alocado a um processo, habilitando
a biblioteca de usurio a designar diferentes threads para executar simultaneamente
em processadores mltiplos.
Quando um thread de usurio bloqueia, o sistema operacional salva o estado
do thread para sua ativao de escalonador e cria uma ativao de escalonador para
notificar a biblioteca de usurio que um de seus threads bloqueou. Ento a biblio
teca de suporte a threads de usurio pode salvar o estado do thread bloqueado da
sua ativao de escalonador e designar um thread diferente para aquela ativao
de escalonador. Esse mecanismo impede que o processo multithread inteiro fique
bloqueado por causa do bloqueio de um de seus threads.26
A limitao primordial do modelo de thread muitos-para-muitos que ele com
plica o projeto do sistema operacional e no h um modo-padro para implement-
-lo.27 Por exemplo, o modelo muitos-para muitos do sistema Solaris 2.2 permitia que
aplicaes de usurio especificassem o nmero de threads de ncleo designados para
Tratadores de sinal
Threads
T1 T2 T3
Mscaras de sinal
Legenda
- No mascarado
- Mascarado
Sinal
threads. Mais importante, no se pode usar o sinal de matar para terminar determi
nado thread quando um thread age obedecendo a um sinal de matar, o processo
inteiro, incluindo todos os seus threads, terminaro. Esse exemplo demonstra uma
outra propriedade importante do modelo de sinal POSIX: embora as mscaras de
sinais sejam armazenadas individualmente em cada thread, as rotinas de tratamento
de sinais so globais para todos os threads de um processo.41, 42
Para terminar um thread particular, o POSIX fornece uma operao de cancelamento
que especifica um thread visado e cujo resultado depende do modo de cancelamento
desse thread. Se o thread visado preferir cancelamento assncrono, ele poder ser
terminado a qualquer momento durante sua execuo. Se o thread adiar o cancela-
mento, ele no ser cancelado at verificar, explicitamente, se h uma requisio de
cancelamento. O cancelamento adiado permite que um thread conclua uma srie de
operaes antes de ser abruptamente terminado. Um thread tambm pode desabili-
tar o cancelamento, o que significa que ele no notificado sobre uma operao de
cancelamento ter sido requisitada.43
Alm das operaes comuns discutidas na Seo 4.5, Operaes de thread, a
especificao POSIX fornece funes que suportam operaes mais avanadas. Ela
permite que programas especifiquem vrios nveis de paralelismo e implementem uma
variedade de polticas de escalonamento, entre elas algoritmos definidos por usurio e
escalonamento em tempo real. A especificao tambm aborda sincronizao usando
travas, semforos e variveis de condio.44, 45, 46
Hoje, poucos dos sistemas operacionais mais populares fornecem implementaes
Pthread nativas completas, ou seja, no ncleo. Todavia, as bibliotecas de suporte
a threads do POSIX existem para fornecer uma ampla faixa de suporte para vrios
sistemas operacionais. Por exemplo, embora o Linux no esteja em conformidade
com o padro POSIX por definio, o projeto Native POSIX Thread Library (NPTL)
visa fornecer uma biblioteca de suporte a threads conforme o padro POSIX que
emprega threads de ncleo no Linux.47 Similarmente, a interface para a linha de
sistemas operacionais Microsoft Windows (API Win 32) no segue o padro POSIX,
mas os usurios podem instalar um subsistema POSIX. [Nota: O sistema operacional
Solaris 9 da Sun Microsystems fornece duas bibliotecas de suporte a threads: uma
biblioteca de Pthreads em conformidade com o padro POSIX e uma biblioteca de
threads herdada do Solaris (denominada threads de interface do usurio (UI). H
pouca diferena entre Pthreads e threads Solaris esse ltimo foi projetado para
que chamadas a funes de thread Pthreads e Solaris vindas de dentro da mesma
aplicao fossem vlidas.48
Linux suporte threads, importante observar que muitos dos seus subsistemas de
ncleo no distinguem entre threads e processos. De fato, o Linux aloca o mesmo
tipo de descritor de processo a processos e threads, ambos denominados tarefas.
O Linux usa a chamada ao sistema baseada no UNIX, denominada Fork, para criar
tarefas-filha. O Linux responde chamada ao sistema Fork criando uma tarefa que
contm uma cpia de todos os recursos de seu pai (por exemplo, espao de endere
amento, contedos de registradores, pilha).
Para habilitar o funcionamento de threads, o Linux fornece uma verso modi
ficada da chamada ao sistema Fork denominada clone. Similarmente Fork, clone
cria uma cpia da tarefa que est chamando na hierarquia do processo a cpia se
torna uma filha da tarefa que emitiu a chamada ao sistema clone. Diferentemente
de Fork, clone aceita argumentos que especificam quais recursos compartilhar com
o processo-filho. No nvel mais alto de compartilhamento de recursos, as tarefas
criadas por clone correspondem aos threads discutidos na Seo 4.2 Definio
de thread.
A partir da verso 2.6 do ncleo, o Linux fornece um mapeamento de thread
um-para-um que suporta um nmero arbitrrio de threads no sistema. Todas as
tarefas so gerenciadas pelo mesmo escalonador, o que significa que processos
e threads de igual prioridade recebem o mesmo nvel de servio. O escalonador
foi projetado para escalar bem at um grande nmero de processos e threads. A
combinao de um mapeamento um-para-um com um algoritmo de escalonamento
eficiente oferece ao Linux uma implementao de thread de alta escalabilidade.
Embora no suporte threads POSIX por definio, o Linux distribudo com uma
biblioteca de suporte a threads POSIX. No ncleo 2.4 uma biblioteca de suporte a
threads, denominada LinuxThreads, fornecia funcionalidade POSIX, mas no estava
totalmente em conformidade com a especificao POSIX. Um projeto mais recente,
Native POSIX Thread Library (NPTL), atingiu uma conformidade quase completa
com o POSIX e provavelmente se tornar a biblioteca de suporte a threads-padro
para o ncleo 2.6.50
Cada tarefa da tabela de processo armazena informaes sobre seu estado corrente
(por exemplo, em execuo, parada, morta). Uma tarefa que est no estado de execu-
o pode ser despachada para um processador (Figura 4.7). Uma tarefa entra no estado
adormecido quanto est dormindo, bloqueada ou no pode executar em um processador
por qualquer outra razo.
Ela entra no estado parado quando recebe um sinal de parada (isto , de
suspenso). O estado zumbi indica que uma tarefa foi terminada, mas ainda no
foi removida do sistema. Por exemplo, se uma tarefa contiver diversos threads, ela
entrar em estado zumbi enquanto notifica seus threads que recebeu um sinal de
trmino. Uma tarefa no estado morto pode ser removida do sistema.
criao
ativa
Poro de Desbloquear
Despachada
tempo expira,
tarefa interativa adormecida
Nova
em execuo
poca
Poro Sinal de
parada
de tempo Continuar
expira
Tarefa sai
do sistema
morta
Fibras
Threads podem criar fibras; elas so semelhantes a threads, exceto que escalo
nada para execuo pelo thread que a cria, e no pelo escalonador. Fibras facilitam
aos desenvolvedores portar aplicaes que empregam threads de usurio. Uma fibra
executa no contexto do thread que a cria.53
A fibra deve manter informao de estado, como a prxima instruo a executar nos
registradores do processador. O thread armazena essa informao de estado para cada
fibra. O prprio thread tambm uma unidade de execuo e, por isso, deve converter-se
a si mesmo em uma fibra para separar sua prpria informao de estado de outras fibras
que executam em seu contexto. De fato, a API do Windows fora um thread a se converter
em uma fibra antes de criar ou escalonar outras fibras. O contexto da fibra permanece,
e todas as fibras associadas quele thread executam naquele contexto.54
Sempre que o ncleo escalonar um thread que foi convertido a uma fibra para
execuo, a fibra convertida ou uma outra fibra pertencente quele thread executar.
Uma vez obtido o processador, a fibra executa at que o thread em cujo contexto est
executando sofra preempo, ou at passar a execuo para uma outra fibra dentro
daquele thread. Do mesmo modo que threads possuem seu prprio armazenamento
local de threads (TLS), fibras possuem seu armazenamento local de fibras (Fiber
Local Storage FLS) que funciona para elas exatamente como o TLS funciona para
um thread. Uma fibra tambm pode acessar os TLSs de seus threads. Se uma fibra
se destruir (terminar), seu thread tambm terminar.55
Reservatrio de threads
O Windows XP tambm fornece um reservatrio de thread (thread pool) para cada
processo. Esse reservatrio consiste em vrios threads operrios, ou seja, threads de modo
ncleo que executam funes especificadas pelos threads de usurios. Como o nmero
de funes especificadas por threads de usurios pode exceder o nmero de threads
operrios, o Windows XP mantm as requisies para executar funes em uma fila. O
reservatrio de threads consiste em threads operrios que dormem at que uma requisio
entre na fila do reservatrio.56 O thread que colocar uma requisio em fila deve especificar
a funo a executar e fornecer informao de contexto.57 O reservatrio de threads
criado na primeira vez que um thread apresentar uma funo ao reservatrio.
O reservatrio de threads tem muitas finalidades. Servidores Web e bancos de dados
podem us-lo para manipular requisies de clientes (por exemplo, navegadores Web).
Em vez de incorrer na sobrecarga dispendiosa de criar e destruir um thread para cada
requisio, o processo simplesmente enfileira a requisio no seu reservatrio de threads
operrios. E mais, diversos threads que passam a maior parte do seu tempo dormindo
(esperando que ocorram eventos) podem ser substitudos por um nico thread operrio
que acorda toda vez que um desses eventos ocorrer. Alm disso, aplicaes podem usar
o reservatrio de threads para executar E/S assncrona enfileirando uma requisio no
seu reservatrio de threadsoperrios para executar as rotinas de concluso da E/S. Usar
reservatrio de threads pode tornar uma aplicao mais eficiente e simples, porque os
desenvolvedores no tm de criar e destruir um nmero to grande de threads. Contudo,
os reservatrios de threads transferem um certo controle do programador para o sistema,
o que pode introduzir ineficincia. Por exemplo, o sistema aumenta e reduz o tamanho
do reservatrio de threads de um processo em resposta a um volume de requisies; em
alguns casos, o programador pode estimar melhor quantos threads so necessrios.58
Estados de threads
No Windows XP, threads podem estar em qualquer um de oito estados (Figura
4.8). Um thread comea no estado inicializado durante a criao do thread. Uma
vez concluda a inicializao, o thread entra no estado pronto. Threads no estado
pronto esto esperando para usar um processador. Um thread que o despachante
decidiu que executar em seguida entra no estado de reserva enquanto espera sua
vez para obter um processador. Um thread est no estado de reserva, por exemplo,
durante o chaveamento de contexto de um thread que estava executando anterior
mente para aquele thread. Uma vez obtido o processador, o thread entra no estado
de execuo. Um thread sai do estado de execuo se concluir a execuo, exaurir
seu quantum, sofrer preempo, for suspenso ou esperar um objeto. Quando um
thread conclui suas instrues, ele entra no estado terminado. O sistema no precisa
necessariamente eliminar um thread terminado imediatamente, o que pode reduzir
a sobrecarga de criao do thread se o processo reinicializ-lo. O sistema elimina um
thread aps a liberao de seus recursos. Se um thread em execuo sofrer preempo
ou exaurir seu quantum, voltar ao estado de pronto.
Um thread em execuo entra no estado de espera enquanto estiver no aguardo
por um evento (por exemplo, um evento de concluso de E/S). E um outro thread (com
suficientes direitos de acesso), ou o sistema, tambm pode suspender um thread forando-
-o a entrar no estado de espera at que o thread seja retomado. Quando o thread concluir
sua espera, retornar ao estado de pronto ou entrar em estado de transio. O sistema
colocar um thread em estado de transio se seus dados no estiverem disponveis
correntemente (por exemplo, porque o thread no executou recentemente e o sistema
necessitou de sua memria para outras finalidades) mas, fora isso, o thread est pronto
para executar. O thread entrar em estado pronto assim que o sistema devolver a pilha
do ncleo do thread memria. O sistema coloca um thread no estado desconhecido
quando o estado do thread no estiver claro (usualmente devido a um erro).59, 60
inicializado transio
ria a da
Criao mo ibiliz
Me pon
dis
Esp
pronto era
rc
on Esperar concluso,
Pr clu mas memria
e e mp
Execuo
indisponvel
s
pendente
o
o
de reserva em espera
exp
Pr
nd
o
m Despachado
ee o
era jet o
ir a
p s p
ob
do o E s
o
qu
ou u m pen
ant u s
um em execuo ou s
Trmino
desconhecido
terminado
portabilidade atravs das plataformas mais populares. Este estudo de caso presume
um conhecimento bsico de Java.
Nesta seo revisamos vrios mtodos relativos a threads na API Java. Usamos
muitos desses mtodos em exemplos de cdigos vivos. O leitor deve consultar dire
tamente a API Java para mais detalhes na utilizao de cada mtodo, especialmente
as excees apresentadas por cada um deles (consulte java.sun.com/j2se/1.4/docs/
api/java/lang/Thread.html).
O cdigo que faz o trabalho real de um thread colocado em seu mtodo run. O
mtodo run pode ser deixado de lado em uma subclasse de Thread ou implementado
em um objeto Runnable; Runnable uma interface Java que permite que o progra
mador controle o ciclo de vida de um thread com o mtodo run em um objeto de uma
classe que no estenda Thread.
47 } // termine try
48
49 // se thread interrompido durante o sono, imprima cpia da pilha ( stack trace )
50 catch ( InterruptedException exception ) {
51 exception.printStackTrace();
52 } // termine catch
53
54 // imprima nome do thread
55 System.err.println( getName() + terminou de dormir );
56
57 } // termine mtodo run
58
59 } // termine classe PrintThread
Amostra de resultado 1:
Ativando threads
Threads ativados, main termina
thread1 vai dormir por 1217 milissegundos
thread2 vai dormir por 3989 milissegundos
thread3 vai dormir por 662 milissegundos
thread3 terminou de dormir
thread1 terminou de dormir
thread2 terminou de dormir
Amostra de resultado 2:
Ativando threads
thread1 vai dormir por 314 milissegundos
thread2 vai dormir por 1990 milissegundos
Threads ativados, main termina
thread3 vai dormir por 3016 milissegundos
thread1 terminou de dormir
thread2 terminou de dormir
thread3 terminou de dormir