Quando você dorme um fio, o que realmente está acontecendo?
Vejo que dormir um encadeamento "pausa o encadeamento atual por um determinado período de tempo" . Mas como isso funciona?
De acordo com Como Thread.sleep () funciona internamente e como o Thread.sleep realmente funciona? :
- a duração do sono estará sujeita a alguma granularidade específica do sistema
- o sono está bloqueando
- o thread sai da CPU e interrompe sua execução
- o encadeamento não está consumindo tempo de CPU enquanto dorme
Simplesmente não consigo entender bem a mecânica interna e fundamental do que tudo isso significa.
Entendo que existe algo chamado agendador responsável pela alternância entre threads.
As fontes parecem indicar que isso varia de acordo com o sistema operacional (ou hardware?) E a maioria dos threads recebe de 1 a 60 ms para executar algumas ações antes que a CPU mude para outro thread.
Mas quando um thread dorme (por exemplo, muitos segundos), como ele é retomado? Acho que um temporizador está envolvido de alguma forma, é o relógio da placa-mãe? Está relacionado à taxa de clock da CPU?
E mesmo que um temporizador esteja envolvido, como a CPU sabe quando é hora de prestar atenção ao encadeamento novamente? Não seria necessário verificar constantemente o tópico para ver se está pronto? Isso não está efetivamente pesquisando e, portanto, está consumindo tempo de CPU?
O modo de suspensão é específico do idioma do encadeamento ou o SO é responsável por isso ou é específico da CPU?
Alguém poderia me explicar isso com explicações básicas de coisas como o agendador e o que a CPU está fazendo durante tudo isso?
fonte
Respostas:
Há muito mais envolvido na execução de um programa do que apenas o código dentro desse programa.
Qualquer programa que é executado em um sistema operacional com vários processos está sob o controle do agendador do sistema operacional , e o agendador mantém uma tabela explícita dizendo qual processo está em execução, quais estão aguardando para serem executados quando os ciclos da CPU estão disponíveis e quais nem são tentando correr (dormindo). O agendador normalmente atribui fatias de tamanho uniforme aos processos, dependendo de sua prioridade e histórico de execução. Por fim, esse loop é causado por interrupções de hardware, geralmente geradas por um oscilador na placa principal.
Dormir é sempre um recurso que uma linguagem de programação pode suportar apenas porque o ambiente de tempo de execução em que será executado o suporta. Um programa normal não pode suspender -se , ele só pode dizer o programador como ele iria gostar de ser tratado - e o programador não é de forma obrigado ou mesmo sempre capazes de satisfazer esse desejo. Pense em um laptop sendo fechado e entrando em hibernação; o oscilador da placa principal continua pulsando, mas, como o agendador não está em execução, nenhum processo pode estar em execução, independentemente da sua prioridade.
fonte
Como Doc Brown mencionou em um comentário, interrupções são a chave, e não apenas para dormir.
Uma interrupção é um sinal de hardware de que o processador deve parar o que está fazendo e executar um pedaço de código. Dispositivos externos acionam interrupções quando precisam da atenção do processador: por exemplo, quando um disco termina de ler os dados, pressiona uma tecla ou um contador regressivo na placa-mãe atinge zero.
O código de manipulação de interrupção geralmente é muito pequeno e muito rápido. Por exemplo, quando o disco indica que um bloco foi copiado na memória, o sistema operacional pode simplesmente registrar esse fato em uma lista de "blocos prontos" em algum lugar e depois retornar ao que quer que esteja fazendo. Você não quer que a CPU gaste todo o seu tempo no código de manipulação de interrupções e não executando o código do usuário.
Um pedaço de código acionado por interrupção que não é necessariamente pequeno é o agendador. É acionado por um sinal de um temporizador de contagem regressiva e examina o estado do sistema sempre que é executado. Isso normalmente inclui a identificação de processos que estão prontos para execução (por exemplo, porque o bloco que eles estavam esperando chegou na memória), bem como aqueles que esgotaram seu intervalo de tempo.
Portanto, quando você executa uma suspensão do encadeamento, o que está fazendo é dizer ao sistema operacional que (1) você está desistindo da sua fatia de tempo e (2) não deve ser acordado novamente até que um certo tempo tenha decorrido.
Sempre que o agendador for executado, ele analisará seu encadeamento e o marcará como "pronto para executar" se esse tempo tiver decorrido. Essa é uma pesquisa, de um tipo, mas não é uma pesquisa de "ciclo ocupado", pois é acionada por uma interrupção. Também não é tão caro: normalmente existem apenas cerca de mil threads em execução por vez.
Isso também deve lhe dar uma idéia de por que os tempos de suspensão não são exatos: quando o encadeamento ficar pronto para execução, poderá haver outros encadeamentos que ainda estejam em execução e que não tenham esgotado sua fatia de tempo. Ou pode haver threads de prioridade mais alta prontos para execução.
fonte