Threads Prof. Alexandre Monteiro Recife ‹#› Contatos Prof. Guilherme Alexandre Monteiro Reinaldo Apelido: Alexandre Cordel E-mail/gtalk: [email protected] [email protected] Site: http://www.alexandrecordel.com.br/fbv Celular: (81) 9801-1878 Thread Ambiente Monothread • Em um ambiente monothread um processo só suporta um programa no seu espaço de endereçamento • Neste ambiente aplicações concorrentes são implementadas só com o uso de processos independentes ou subprocessos - Nestes casos a aplicação é dividida em partes que podem trabalhar concorrentemente. De forma simplificada um thread pode ser definido como uma sub-rotina de um programa que pode ser executada de forma assíncrona. Ou seja, executada paralelamente ao programa chamador. Ambiente Monothread A limitação da abordagem monothread é que o uso de processos consomem muitos recursos do sistema Quando um processo é criado/eliminado deve-se alocar/desalocar recursos do sistema Além disso, como cada processo tem seu espaço de endereçamento, a comunicação entre processos é mais lenta •A comunicação pode usar pipes, sinais, trocas de mensagens,... Na abordagem monothread cada processo tem seu próprio contexto de HW, SW e Espaço de Endereçamento, o que dificulta a comunicação entre processos Ambiente Multithread Neste ambiente não existe a idéia de programas associados a processos, mas, sim, a threads O processo tem pelo menos um thread de execução, mas pode compartilhar o seu espaço de endereçamento com outros threads Thread A grande diferença entre ambientes monothread e multithread está no uso do espaço de endereçamento • Processos independentes ou subprocesso possuem espaços de endereçamento individuais e protegidos • Multithreads compartilham o espaço de endereçamento dentro de um mesmo processo - Como os threads compartilham o mesmo espaço de endereçamento, não se exige mecanismos para proteção no acesso a memória - Isso permite que o compartilhamento de dados entre threads de um mesmo processo seja mais simples e rápido Ambiente Multithread Cada thread possui seu próprio contexto de HW, porém divide o mesmo contexto de SW e espaço de endereçamento com os demais threads do processo Thread O programador especifica os threads associando-os às subrotinas assíncronas • É assim que se obtém a execução concorrente de subrotinas dentro de um mesmo processo Por exemplo: • Um programa principal (calculadora) com 4 subrotinas assíncronas (+,-,*,/) - Chama-se primeiro o thread do PP, o qual chama os 4 threads - Os 4 threads são executados independentemente do PP - E os 5 threads são executados concorrentemente Thread Thread No ambiente multithread cada processo pode responder a várias solicitações concorrentemente ou simultaneamente (caso haja mais de uma CPU) A vantagem no uso de threads é a possibilidade de minimizar a alocação de recursos do sistema Threads compartilham a CPU igualmente a processos •EX: enquanto um thread espera uma E/S, outro é executado Thread Threads passam pelas mesmas mudanças de estado • (a) Pronto -> Execução • (b) Execução -> Bloqueado/Espera • (c) Bloqueado/Espera -> Pronto • (d) Execução -> Pronto Para permitir a troca de contexto cada thread tem seu próprio contexto de HW • Thread em execução -> registradores ficam na CPU • Thread parado -> registradores no seu contexto de HW Thread Semelhante a processos, threads são implementados internamente através de uma estrutura de dados Bloco de Controle de Thread (Thread Control Block - TCB) •O TCB armazena, além do contexto de HW, dados exclusivos sobre o thread, como prioridade e estado de execução •PCB X TCB ? Implementação de Threads de Usuário Um pacote de threads de usuário 13 Implementação de Threads de Núcleo PCB TCB Um pacote de threads gerenciado pelo núcleo 14 Threads de Núcleo Não é necessário o sistema de tempo de execução (runtime), pois o núcleo possui uma tabela de todas as threads no sistema. As informações são as mesmas das threads de usuário, porém agora estão no espaço do núcleo, mantidas em uma tabela de threads e outra tabela de processos. Todas as chamadas implementam chamdas de sistema (System Calls) a um custo considerável maior que as chamadas de (runtime). Tentam executar todas as threads de um processo para só então chavear o processo. Custo alto de chamadas de sistema = Reciclagem de threads. Implementações Híbridas Multiplexação de threads de usuário sobre threads de núcleo 16 Threads Híbridas Multiplexar threads de usuários sobre threads de núcleo. O núcleo sabem apenas sobre as threads de núcleo. Cada thread de núcleo possui algum conjunto de threads de usuário que aguarda sua vez para usar o processador. Threads (ou Processo Leve) Thread é uma unidade básica de utilização da CPU, que consiste em: 1. Apontador de instruções 2. Conjunto de registradores 3. Espaço de pilha Uma Thread compartilha com Threads irmãs: 1. Área de código 2. Área de Dados 3. Recursos do SO (coletivamente conhecidos como tarefas) Um Processo tradicional é equivalente uma tarefa com uma única Thread. Interação entre Threads TCB 1 TCB 2 Múltiplas Threads em uma tarefa TCBs Thread Foi introduzido para reduzir o tempo gasto na criação, eliminação e troca de contexto de processos Em um ambiente multithead um processo suporta múltiplos threads (um para cada parte do código da aplicação) • Neste caso não há a necessidade de vários processos para a implementação da concorrência. • Isto permite compartilhar o espaço de endereçamento e o contexto de SW entre os threads e garantir que cada thread seja executado de forma independente Threads O Modelo de Thread (1) (a) Três processos cada um com um thread (b) Um processo com três threads 22 Thread - Benefícios Numa Thread dotada de múltiplos fluxos de execução, enquanto um fluxo está bloqueado, um outro fluxo na mesma tarefa pode continuar executando Cooperação de múltiplas threads em uma mesma tarefa aumenta o throughput (quantidade de dados processados em um determinado espaço de tempo) e o desempenho. Aplicações que requerem o compartilhamento de Buffers (Ex. produtores e consumidores) se beneficiam da utilização de threads. O mecanismo de thread permite que processos sequenciais sejam executados paralelamente, apesar de poderem fazer chamadas ao sistema que bloqueiam processos Threads: Motivação Concorrência Problemas: •Programas que precisam de mais poder computacional •Dificuldade de implementação de CPUs mais rápidas Solução: •Construção de computadores capazes de executar várias tarefas simultaneamente Problema da Concorrência Não-determinismo – x = 1 || x = 2 • Qual o valor de “x” após a sua execução? Dependência de Velocidade – [[ f(); x = 1 ]] || [[ g(); x = 2 ]] – O valor final de x depende de qual das funções, f() e g(), terminar primeiro Starvation – Processo de baixa prioridade precisa de um recurso que nunca é fornecido a ele... Problemas de Concorrência Deadlock •Um sistema de bibliotecas só fornece o “nada consta” para alunos matriculados e o sistema de matricula só matricula os alunos perante a apresentação do “nada consta” – Definição: dois processos bloqueiam a sua execução pois um precisa de um recurso bloqueado pelo outro processo. Conceitos: starvation e deadlock (Veremos mais detalhes) O Modelo de Thread (2) Compartilhados • • Privativos Items compartilhados por todos os threads em um processo Itens privativos de cada thread 27 O Modelo de Thread (3) Cada thread tem sua própria pilha 28 Thread Em ambientes cliente-servidor, múltiplos threads permitem que diversos pedidos sejam atendidos simultaneamente Em multithread um thread pode solicitar um serviço remoto, e a aplicação pode continuar executando outras atividades. Em monothread uma aplicação pode ficar esperando indefinidamente o resultado de um serviço remoto Thread Thread Arquitetura e implementação Pacote de threads = conjunto de rotinas para que uma aplicação utilize threads Tipos de arquiteturas mais usuais •Threads em Modo Usuário •Threads em Modo Kernel Thread em modo usuário São implementados pela aplicação e não pelo SO Deve existir uma biblioteca de rotinas que possibilite à aplicação realizar tarefas como: • Criação/eliminação de threads • Troca de mensagens entre threads • Política de escalonamento Neste modo o SO desconhece a existência de múltiplos threads, sendo responsabilidade da aplicação gerenciar/sincronizar os threads A troca de contexto entre threads é feita em modo usuário pelo escalonador embutido em uma biblioteca: - Não necessita privilégios especiais - Escalonamento depende da implementação Thread em modo usuário A vantagem desse modelo é a possibilidade de implementar aplicações multithreads mesmo em SO monothread É rápida e eficiente, pois dispensa acessos ao kernel, •Isto evita a mudança de modo de acesso (Usuário-Kernel-Usuário -> realiza TRAP) Implementação de Threads de Usuário Um pacote de threads de usuário 34 Threads em Modo Usuário Inserido no espaço do usuário e implementados por uma biblioteca, executados em um sistema de tempo de execução (runtime = coleção de rotinas que gerenciam threads). O núcleo não é informado sobre eles, pois o núcleo gerencia processos normais monothreads, e o chaveamento entre threads de usuário é mais rápido que desviar o controle para o núcleo. 1ª vantagem é que pode ser implementado em um SO que não suportada threads e 2ª vantagem é que permitem a cada processo ter seu próprio algoritmo de escalonamento. Usa Tabela de Threads (TCB) para manter o controle das threads naquele processo e escalonam melhor, pois dividem o mesmo espaço de endereçamento e contexto de software. Desvantagem é chavear threads de processos realizando trap. Threads de Modo Usuário Sua grande limitação é o fato do SO gerenciar cada processo como se existisse apenas um único thread • No momento que um thread entra em estado bloqueado/espera todo o processo é colocado em bloqueado/espera • Para contornar isso, a biblioteca deve ter rotinas que substituam as rotinas bloqueadas por outras que não possam bloquear um thread - Todo esse controle é transparente para o usuário e SO O fato do SO gerenciar o processo como um thread, também compromete o escalonamento e o tratamento de sinais • Os sinais enviados para um processo devem ser reconhecidos e enviado para cada thread • O escalonamento não é possível, pois os múltiplos threads de um processo não são executados em CPUs diferentes simultaneamente - Os threads de um processo são executados em uma CPU por vez Exemplo de Thread (runtime) Biblioteca: executados em um sistema de tempo de execução (runtime = coleção de rotinas que gerenciam threads). Exemplo de Thread (runtime) São implementados diretamento pelo Kernel, através de chamadas a rotinas do SO O SO conhece cada thread e escalona-os individualmente No caso de múltiplas CPUs, os threads de um mesmo processo podem ser executados simultaneamente Sua grande limitação é seu baixo desempenho • Exige muita troca de modo de acesso (Usuário-Kernel-Usuário) Implementação de Threads de Núcleo PCB TCB Um pacote de threads gerenciado pelo núcleo 39 Modelo de Programação Um fator importante em multithread é o total de threads •Muitos threads poderão sobrecarregar o sistema (desempenho ruim) Para usufruir de thread, uma aplicação deve permitir que partes do seu código executem em paralelo e independente Se um aplicativo executa muitas E/S e trata eventos assíncronos, a multithread aumenta o desempenho •EX: SGBDs, Servidores de Impressão O desenvolvimento multithread não é simples, exigindo muito sincronismos para evitar problemas de inconsistência e deadlock. Uso de Thread (1) Thread formata e reformata o conteúdo em segundo plano a medida em que o usuário digita novos teto do editor Thread interativo com o usuário, trata dos textos digitados pelo usuário Thread que realiza backups em disco a cada período de tempo, sem interferir nos outros dois. Um processador de texto com três threads 41 Uso de Thread (2) Um servidor web com múltiplos threads 42 Uso de Thread (3) (a) Thread despachante: lê as requisições de trabalho que chegam da rede. (b) Depois de examinar a requisição ele escolhe o Thread Operário ocioso (bloqueado) e entrega-lhe a requisição, colocando –o em estado de pronto. Em seguida o operário verifica se a requisição está na cache de páginas web. Se estiver entrega-o ao cliente e bloqueia o operário. Senão, bloqueia e procura em disco. Enquanto isso, outra requisição do despachante é atendida. 43 Uso de Thread (4) Três maneiras de construir um servidor 44 Ativações do Escalonador Objetivo – imitar a funcionalidade dos threads de núcleo • ganha desempenho de threads de usuário Evita transições usuário/núcleo desnecessárias Núcleo atribui processadores virtuais para cada processo – deixa o sistema supervisor alocar threads para processadores Problema: Baseia-se fundamentalmente nos upcalls - o núcleo (camada inferior) chamando procedimentos no espaço do usuário (camada superior) 45 Implementando modelo N:1 Vantagens e Desvantagens Vantagens: • SO divide o tempo do processado entre os processos “pesados” e, a biblioteca de threads divide o tempo do processo entre as threads, sem interação/intervenção do SO. Desvantagens • Uma thread que realiza uma chamada de sistema bloqueante leve ao bloqueio de todo o processo - Operações de entrada/saída • Não explora paralelismo em máquinas multiprocessadoras. Implementando modelo 1:1 Modelo 1:1 Threads a nível de sistema • Kernel Level Threads ou ainda System Scope Resolver desvantagens do modelo 1:1 • SO mantém informações sobre processos e sobre threads • Troca de contexto necessita da intervenção do SO O conceito de thread é considerado na implementação do SO. Vantagens: • Explora paralelismo de máquinas multiprocessadoras • Facilita o recobrimento de entrada/saída por cálculos Desvantagens • Implementação mais pesada que o modelo N:1 Implementando modelo M:N Modelo M:N Abordagem que combina modelo N:1 e 1:1 Oferece dois níveis de escalonamento •Nível usuário: threads sobre unidade de escalonamento •Nível sistema: unidades de escalonamento sobre processador Dificuldade é parametrizar M e N Processos X Threads Tipos de sistemas •1 processo com 1 thread: MSDOS •N processos, cada um com 1 thread: OS/386, VAX/VMS, Windows 3.1, UNIX antigo •1 processo com N threads: kernels para sistemas embarcados •N processos, cada um com N threads: Windows 95/98,NT, UNIX Threads Pop-Up Requisição de serviço Criação de um novo thread quando chega uma mensagem (a) antes da mensagem chegar (b) depois da mensagem chegar 53 Threads Pop-up Normalmente usado em sistemas distribuídos são threads novos sem qualquer história (registradores, pilhas, TCB) que deva ser restaurada e inicia recém-criado e é igual ao demais Ao novo thread é dada uma mensagem para processar: (mensagem chega, é aceita, conteúdo examinado e então é processada) A vantagem é que a latência entre a chegada da mensagem e o início do processamento pode ser muito pequena Pode executar no espaço do núcleo ou do usuário, mas no núcleo é, em geral, mais fácil e rápido Além disso, no núcleo pode ter acesso a todas as tabelas e aos dispositivos de E/S necessários ao processamento de interrupções. Planejamento prévio: (em qual processo o thread executa?) Porque utilizar threads? Permitir o paralelismo real oferecidos por máquinas multiprocessadores (modelo N:1 e 1:1) Aumentar o número de atividades executadas por unidade de tempo (throughput) Diminuir o tempo de resposta • Possibilidade de associar threads a dispositivos de E/S Sobrepor operações de cálculo com operações de E/S Vantagens de Mutithreading Tempo de criação/destruição de threads é inferior ao tempo de criação/destruição de processos Chaveamento de contexto entre threads é mais rápido em tempo que chaveamento entre processos Como threads compartilham o descritor do processo que as contem, elas dividem o mesmo espaço de endereçamento o que permite a comunicação por memória compartilhada, sem interação com o núcleo Referências Sistemas Operacionais Modernos – 3ª Edição. A. Tanenbaum, 2008. Modern Operating Systems 3 e. Prentice-Hall, 2008.