Explicação detalhada do agendamento de encadeamento Java

No artigo sobre segurança de thread, mencionamos que, para um computador com uma única CPU, apenas uma instrução de máquina pode ser executada a qualquer momento, e cada thread só pode executar instruções se obtiver o direito de usar a CPU.

A chamada operação simultânea de vários threads na verdade significa que, de uma perspectiva macro, cada thread obtém o direito de usar a CPU por vez e executa suas próprias tarefas, respectivamente.

Na introdução anterior ao estado da thread, sabemos que o estado em execução da thread contém dois subestados, a saber, pronto (READY) e em execução (RUNNING).

E se um thread quiser mudar do estado pronto para o estado em execução, esse processo requer agendamento do sistema, ou seja, o thread recebe o direito de usar a CPU e o thread que obteve o direito de usar a CPU mudará do estado pronto para o estado em execução.

O processo de atribuição de direitos de uso da CPU a vários threads de acordo com um mecanismo específico é chamado de escalonamento de threads.

Lembre-se da frase que mencionamos quando introduzimos a diferença entre processos e threads: um processo é a unidade básica de alocação de recursos e um thread é a unidade básica de escalonamento da CPU. O agendamento mencionado aqui refere-se à atribuição de fatias de tempo de CPU a ele e permite que ele execute tarefas.

Agendamento de encadeamento do Linux

No Linux, um thread é implementado por um processo, e um thread é um processo leve (lightweight process), portanto, no Linux, o agendamento de threads é agendado de acordo com o método de agendamento do processo, ou seja, o thread é a unidade de agendamento.

Um dos benefícios dos encadeamentos implementados pelo Linux dessa maneira é que o escalonamento de encadeamento pode usar diretamente o escalonamento de processo e não há necessidade de ter um escalonador de encadeamento em processo. No Linux, o agendador decide qual encadeamento executar com base na política de agendamento de encadeamento (política de agendamento) e na prioridade de agendamento estático (prioridade de agendamento estático).

No Linux, existem basicamente três estratégias de escalonamento. Eles são:

  • SCHED_OTHER estratégia de agendamento de tempo compartilhado, (padrão)
  • SCHED_FIFO estratégia de agendamento em tempo real, primeiro a chegar, primeiro a ser atendido
  • SCHED_RR estratégia de agendamento em tempo real, rotação de fatia de tempo

Agendamento de threads do Windows

O Windows usa um algoritmo de agendamento preemptivo baseado em prioridade para agendar threads.

A parte do kernel do Windows que lida com o agendamento é chamada de agendador, e o agendador do Windows garante que o thread de prioridade mais alta esteja sempre em execução. O thread escolhido para ser executado pelo escalonador será executado até que seja interrompido por um thread de prioridade mais alta, ou encerrado, ou até que a fatia de tempo tenha expirado, ou até que uma chamada de sistema de bloqueio (como E/S) seja chamada. Se um thread de tempo real de prioridade mais alta ficar pronto enquanto um thread de baixa prioridade estiver em execução, o thread de baixa prioridade será interrompido. Essa preempção permite que os threads em tempo real sejam usados ​​primeiro quando precisam usar a CPU.

Agendamento de encadeamento Java

Pode-se ver que diferentes sistemas operacionais possuem diferentes estratégias de escalonamento de threads. No entanto, como um desenvolvedor Java, geralmente prestamos pouca atenção ao nível do sistema operacional em nosso processo de desenvolvimento diário.

O principal motivo é que os programas Java são executados na máquina virtual Java, e a máquina virtual nos ajuda a proteger as diferenças no sistema operacional, por isso dizemos que Java é uma linguagem de plataforma cruzada.

No sistema operacional, um programa Java é, na verdade, um processo. Portanto, dizemos que Java é de processo único e multiencadeado!

Como mencionado anteriormente, a implementação de threads também é significativamente diferente da maioria das APIs Java. Todos os seus métodos-chave são declarados como Nativos. Ou seja, ele precisa de diferentes implementações de acordo com diferentes sistemas operacionais.

No programa multi-thread do Java, para garantir que a execução de todos os threads possa ser executada de acordo com certas regras, a JVM implementa um escalonador de threads, que define o modelo de escalonamento de threads e estipula a alocação de operações da CPU. direitos de uso para vários segmentos.

Existem dois modelos principais de escalonamento: escalonamento de thread cooperativo e modelo de escalonamento preemptivo .

escalonamento de thread cooperativo

No sistema multi-threaded de escalonamento cooperativo, o tempo de execução do thread é controlado pelo próprio thread.Depois que o thread termina de executar seu próprio trabalho, ele deve notificar ativamente o sistema para alternar para outro thread. A maior vantagem do multi-threading cooperativo é que é fácil de implementar e, como o thread alternará depois de terminar seu próprio trabalho, a operação de alternância é conhecida pelo próprio thread, portanto, não há problema de sincronização do thread.

Modelo de Agendamento Preemptivo

Em um sistema multithread com escalonamento preemptivo, cada thread terá um tempo de execução alocado pelo sistema, e a troca de thread não é determinada pela própria thread. Nesta forma de implementar o agendamento de threads, o tempo de execução dos threads é controlável pelo sistema e não haverá problema se um thread causar o bloqueio de todo o processo.

O sistema permitirá que threads com alta prioridade no pool executável ocupem a CPU. Se os threads no pool executável tiverem a mesma prioridade, selecione aleatoriamente um thread para ocupar a CPU. Uma thread no estado running continua rodando até que tenha que liberar a CPU.

A máquina virtual Java adota um modelo de agendamento preemptivo.

Embora o agendamento de encadeamentos Java seja feito automaticamente pelo sistema, ainda podemos "sugerir" o sistema para alocar mais tempo de execução para alguns encadeamentos e alocar menos tempo para outros encadeamentos - essa operação pode ser feita definindo a prioridade do encadeamento . A linguagem Java define um total de 10 níveis de prioridade de encadeamento (Thread.MIN_PRIORITY a Thread.MAX_PRIORITY). Quando dois encadeamentos estão no estado Pronto ao mesmo tempo, é mais provável que o encadeamento com prioridade mais alta seja selecionado pelo sistema para execução.

No entanto, a prioridade do encadeamento não é muito confiável, porque os encadeamentos Java são implementados mapeando os encadeamentos nativos do sistema; um-para-um com a prioridade dos encadeamentos Java.

おすすめ

転載: blog.csdn.net/zy_dreamer/article/details/132364646