Escalonamento de Threads
Introdução
- Máquina com uma única CPU dão a ilusão de paralelismo
- Mesmo com várias CPUs, pode haver mais threads querendo rodar do que CPUs disponíveis
- Portanto, há um mecanismo para dar essa visão que chamamos escalonamento
- A JVM implementa um escalonador de threads simples chamado "escalonamento com
prioridades fixas"
- Threads rodam dependendo de sua prioridade em relação a outros threads
- A prioridade de um thread
- Quando um thread é criado, herda a prioridade do thread criador
- O método setPriority pode ser usado para alterar a prioridade
- Prioridades são inteiros entre MIN_PRIORITY e MAX_PRIORITY
- Um número mais alto dá prioridade "melhor"
- Quando uma CPU vai à procura de um thread para rodar, ela escolhe o thread com melhor
prioridade que esteja pronto para rodar
- Se houver dois ou mais com a mesma prioridade, o escalonador escolhe um deles
aleatoriamente
- O thread executa até que uma das seguintes condições ocorra:
- Um thread de mais alta prioridade se torna pronto para rodar
- Chamamos isso de "preemption"
- O novo thread "preempt" o de mais baixa prioridade
- "preempt" = "tomar o lugar à força"
- O thread cede a CPU (chamando o método yield())
- O método run() termina
- Em sistemas com time-slicing, a fatia de tempo acabou para o thread
- Neste momento, um outro thread pode rodar e assim por diante até que a JVM termine
Corridas entre threads
- RaceApplet é um applet que mostra uma corrida entre
2 threads corredoresde prioridades diferentes
- Clique no applet para iniciar a corrida
- Corredor 2 tem prioridade 2 e corredor 3 tem prioridade 3
- Os corredores são implementados por uma subclasse de Thread chamada Runner
- Eis o método run de Runner:
public void run() {
while (tick < 400000000)
tick++;
}
- O applet tem um terceiro thread para controlar o display
- O método run do thread de display fica em loop até o applet parar
- Em cada iteração, o thread desenha uma linha para cada corredor cujo tamanho é
função da variável tick
- Em seguida, o thread dorme por algum tempo
- A prioridade do thrad de display é 4: deve rodar sempre que estiver querendo
- As linhas devem se arrastar para a direita
- A corrida não é justa devido às prioridades
- Corredor 3 sempre tem prioridade sobre o corredor 2
- Eis um outro applet com prioridade igual para os threads corredores
- A escolha arbitrária entre 2 threads de igual prioridade pelo escalonador equilibrou a
situação
Threads Egoistas e Time Slicing
- O método run que fica contando em loop (acima) é um thread egoista porque não larga a
CPU por vontade própria
- Ele só deixa de rodar se algum thread de maior prioridade "se acordar" (ou
quando acaba)
- Em alguns casos, threads egoistas podem tomar controle da CPU (quando não há outro
thread de maior prioridade ficando pronto)
- Isso ocorre só dentro desse programa
- O escalonador do sistema operacional vai dar chance a todos os processos
- Porém, dentro de um processo, quem controla os threads é a JVM (para um programa
escrito em Java)
- Alguns sistemas usam time slicing para limitar a fatia de tempo que um thread recebe
até largar a CPU (por força alheia, não por vontade própria)
- Não é a JVM que faz time slicing
- É o sistema operacional que está dando suporte a threads (threads do SO são usados
para implementar threads da JVM)
- Normalmente, um thread tem operações de I/O lentas e outras chamadas que podem forçar
a perda da CPU
- Se não houver, o thread pode ser "bonzinho" e largar a CPU usando o método
yield()
- Isso entrega a CPU a outro thread de igual prioridade
- Se não houver, nada faz
programa