Baixe o app para aproveitar ainda mais
Prévia do material em texto
THREADS VISÃO GERAL TÍTULO Sobre a FMU As Faculdades Metropolitanas Unidas - FMU foram criadas em 1968, e o primeiro vestibular aconteceu em julho do mesmo ano, ao qual afluíram centenas de alunos que buscavam formação educacional nos diversos cursos que inicialmente foram oferecidos. Era o início da rápida expansão do ensino superior brasileiro e a instituição FMU marcava sua presença no atendimento da demanda da sociedade brasileira por mais educação superior. Nesse período, de 1968 até hoje, milhares de alunos passaram pelos bancos escolares da FMU, receberam sólida formação educacional e se capacitaram como profissionais com nível para terem elevado desempenho em diferentes setores das atividades econômicas e sociais, tanto no setor privado como no setor público. A aceitação desses profissionais pelo mercado de trabalho é o melhor atestado de excelência do ensino da FMU. Threads O uso de Thread Modelo de Thread Clássico Threads POSIX Implementação de Threads no espaço do usuário Implementação de Threads no núcleo Implementações híbridas Ativações do escalonador Threads pop-up Convertendo o código monothread em código multithread Conteúdo Threads • Em SO´s tradicionais, cada processo tem um espaço de endereçamento e um único Thread de controle. • Entretanto existem situações onde é desejável ter múltiplos Threads de controle no mesmo espaço de endereçamento executando em “quase-paralelo”, como se eles fossem processos separados (exceto pelo espaço de endereçamento compartilhado) • Tornam possível manter a ideia de processos sequenciais e mesmo assim conseguem obter paralelismo • Definições formais: – “Entidades escalonadas para execução” - Tanenbaum – “Fluxo de execução dentro de um processo” - Rômulo Oliveira – “Unidade básica de utilização da CPU” - Silbershatz Num sistema multithread, cada Thread do processo possui o seu contexto de hardware e software (pois uma thread “disputa” a CPU com as outras threads e processos). A diferença com os sub processos é que todas as threads de um processo compartilham o mesmo espaço de endereçamento (gerando concorrência entre as threads). Processos » Meio de agrupar recursos relacionados (arquivos abertos, processos filhos, etc.) Threads » São as entidades escalonadas para execução sobre a CPU (pertencem ao Processo) e permitem múltiplas execuções no mesmo ambiente de processo Processos e Threads O uso de Threads • Porque alguém desejaria ter um tipo de processo dentro de um processo? Existem várias razões para existirem esses “miniprocessos”, chamados de Threads. a) Em muitas aplicações ocorrem múltiplas atividades ao mesmo tempo. Algumas dessas atividades podem ser bloqueadas de tempos em tempos. Como na justificativa da existência de processos, a programação se torna mais simples se decompormos uma aplicação em múltiplos Threads sequenciais que executam em “quase paralelo”. Porém em vez de pensarmos em interrupções, temporizadores e chaveamentos de contexto, podemos pensar em processos paralelos, pois com os Threads, diferentemente dos Processos, podemos utilizar uma novo elemento: A capacidade de entidades paralelas compartilharem o mesmo espaço de endereçamento e todos os seus dados entre elas. b) São mais fáceis (mais rápidas – 100x) de serem criadas e destruídas que os Processos pois não possuem recursos associados a eles. Isto é muito bom quando o número de Threads necessários se altera dinamicamente. c) O uso de Threads resulta em ganho de desempenho quando falamos de processos I/O- Bound (aqueles que exigem um grande volume de operações de E/S), e pouco efeito nos processos CPU-Bound (Aqueles que possuem maior volume de processamento em CPU, p.e., cálculos). d) Também são particularmente úteis em sistemas com múltiplas CPU´s. Exemplos de uso: Processador de texto com três Threads 1. Interage com usuário (Teclado e Tela) 2. Reorganiza o arquivo 3. Cópias em disco (backups) Planilha Eletrônica com três Threads 1. Interage com usuário (Teclado e Tela) 2. Recalcula as formulas a cada alteração 3. Cópias em disco (backups) Como funcionariam com três Processos? Seria possível? Não, pois o compartilhamento do mesmo espaço de endereçamento não ocorreria. O uso de Threads Um Servidor para um Site na Web – Ele deve ser implementados para suportar múltiplas conexões de diferentes (ou dos mesmos) usuários. Devemos considerar o uso de Cache das páginas mais utilizadas e a leitura em disco de páginas menos acessadas. Para suportar e possibilitar um melhor desempenho de clientes WEB, devem ser implantados com Multithread no modelo despachante/operário Threads divididos em: Despachante e Operários O uso de Threads Implementações possíveis de um servidor: Multithreads – Exemplos vistos que apresentam chamadas bloqueantes (p.e. I/O em disco) e paralelismo. Processo Monothread – Apenas um Thread guia dentro do processo, também apresentam chamadas bloqueantes, porem sem o paralelismo do Multithread. Máquina de estados finitos - Não utiliza chamadas bloqueantes, porem as tratas através de interrupções o que obriga que o estado do computador deve ser salvo a cada vez que o servidor chaveia do trabalho de uma requisição para outra, simulando as Threads e suas pilhas de maneira mais difícil. (Máquina de estados finitos, conceito muito utilizado na Ciência da Computação, no qual cada computação tem um estado salvo e existe um conjunto de eventos que podem ocorrer para mudar o estado) O processo pode ser estruturado com 3 Threads. Uma que lê os dados, outra que os processa e uma terceira que grava os dados no disco. Funcionará em paralelismo apenas se apenas o Thread for bloqueado e não o seu processo. O uso de Threads O Modelo de Processos envolve dois conceitos independentes: O agrupamento de recursos e Execução, o que algumas vezes se torna útil separa-los como no caso de Threads Processos » Meio de agrupar recursos relacionados (arquivos abertos, processos filhos, etc.). Coloca-los agrupados em processo torna mais fácil o gerenciamento dos recursos. Threads » São as entidades escalonadas para execução sobre a CPU (pertencem ao Processo) e permitem múltiplas execuções no mesmo ambiente de processo. Possuem Contador de Programas, Registradores e Pilhas (Traz a história da execução, com uma estrutura para cada rotina chamada mas ainda não retornada). Apesar de Thread executar dentro de um processo, são conceitos diferentes e podem ser tratados separadamente. O Termo Multithread em nosso contexto envolve software e quando tratado no contexto de múltiplos core se aplica a um suporte de hardware que faz o chaveamento de threads em uma escala de tempo de nanosegundos (Tanenbaum) O modelo de Thread Clássico Na figura (a) vemos três processos tradicionais (Espaço de endereçamento próprio e único Thread de controle). Na figura (b), temos um processo com três threads que compartilham o espaço de endereçamento. Considerando que temos uma CPU que processa uma instrução por vez, como teríamos o pseudoparalelismo nestas abordagens? Quanto aos processos já vimos o conceito de multiprogramação de processos e o chaveamento entre eles. Quanto ao Multihread, funcionará igual, alternando entre Threads. Quando um processo com multiplos Threads é executado em CPU única, os seus Threads aguardam a vez para processar. O modelo de Thread Clássico Em multithread, compartilham Itens Comuns por processo, como o espaço de endereçamento, utilizando as mesmas váriaveis globais e assim acessando qualquer posição de memória comuns entre Threads daquele processo, podendo alterá-las (incluir, alterar ou excluir), não havendo Proteção entre os Threads, o que não é possível e nem necessário, (temos o domíniodo processo e de seu comportamento, enquanto que entre processos, eles pertencem a usuários diferentes e potencialmente hostis entre si). Outro aspecto importante é que três processos cada um com um thread de controle desempenharam atividades não relacionadas, enquanto que um processo com três threads terão atividades que cooperam entre si. O modelo de Thread Clássico Em Processo tradicional (apenas um Thread) o Thread deste processo poderá estar em dos vários estados possiveis (Em execução, Bloqueado, Pronto e Finalizado), com as mesmas transições de estados de Processos. Em um processo Multithread é importante perceber a necessidade de pilhas para cada Thread. Possuem as variáveis locais da rotina e o endereço de retorno para usa-los quando a rotina chamada terminar. O modelo de Thread Clássico Threads POSIX Padrão de Threads – IEEE 1003.1c. (Institute of Electrical and Electronics Engineers) - Chamado de Pthreads. Mais de 60 chamadas Maiorias de sistemas Unix e Linux suportam Processo Multhread em geral inicia apenas com um Thread, que cria e encerra os que forem necessários. 17 Implementação de Threads CV CV CV CV Threds no Núcleo Threds de Usuário Modos de implementar um pacote de Threads: No espaço do usuário, no núcleo e hibrida: Implementação de Threads de Usuário Inseridos no espaço do usuário e o núcleo não é informado. Fica ao núcleo apenas o gerenciamento de processos monothreads. A vantagem esta em implementar Multithreads em SO´s sem suporte a isso. Implementado por biblioteca (p.e.: POSIX). Cada processo para ter o controle, precisa de sua própria tabela de Threads, tratando do controle e transições de estado de suas Threads. (Com chamadas não bloqueantes e verificações prévias de segurança para a chamada) O Chaveamento de threads de usuário é mais rápido que os de núcleo (Trabalha na tabela de Threads na área de endereçamento comum, elimina chaveamento de contextos, evita limpeza memória, etc.). Cada processo pode ter o seu próprio algoritmo de escalonamento personalizado. Dificuldades: O tratamento de chamadas bloqueantes (contornado com chamada de sistema – Select) e Page fault (Falta de página) que pode causar o bloqueio de todo o processo, mesmo com threads que possam ser executadas. Também não tem Interrupções de relógio, impede o escalonamento circular. Qualidade da implementação pelo programador, com bloqueios excessivos por interrupções de software (Traps) Implementação de Threads no Núcleo São conhecidos pelo Núcleo. A tabela de Threads fica no Núcleo e não mais no Processo. Assim quando se deseja criar ou destruir um Thread deve-se fazer uma chamada ao Núcleo (mais demorado). Todas as chamadas bloqueantes são implementadas como chamadas de sistema (mais demorado), não usa chamadas não bloqueantes (p.e. para E/S). Se um Thread for bloqueado, é opção do Núcleo executar outro Thread do mesmo processo ou não, o que é diferente de quando os Threads estão no Processo (sempre outro thread do mesmo processo será executado, até o processo entrar no estado de bloqueado). Alguns sistemas permitem reciclar Threads devido ao custo de criar e destruir. Desativa o Thread e reutiliza sua estrutura de dados no Núcleo quando necessário. (Possível também na área do usuário, porem o ganho não é tão grande). Se um processo causar uma falta de página (page fault) o Núcleo irá gerenciar de forma a aguardar o carregamento da página do disco. Principal desvantagem de Threads no Núcleo é o custo nas chamadas de sistema. Busca combinar as vantagens de Threads de Usuário com as vantagens de Threads de Núcleo atráves da multiplexação de Threads de usuário sobre Threads de Núcleo. Cria-se a o Thread de Núcleo e sobre ele criam-se Threads de usuário. Dá flexibilidade pois o núcleo só conhece Threads de Núcleo e os Threads de Processo são tratados da mesma forma como se o SO não suporta-se multithread. Multiplexando Threads de usuários sobre Threads de Núcleo Implementações Híbridas de Threads Ativações de Escalonador Threads de Núcleo são consideradas melhores que Threads de Usuário, porém muito mais lentos. Pesquisadores buscam aperfeiçoa-lo sem abrir mão de suas boas propriedades. O método Ativações de Escalonador, desenvolvido por Andersen et al (1992) será discutido abaixo: Objetivo – Imitar a funcionalidade dos Threads de núcleo em Threads de usuário. Ganha desempenho de Threads de usuário (Mas não fariam chamadas bloqueantes ou verificações prévias antes de fazer chamadas) Permite executar outro Thread dentro do mesmo processo em caso de bloqueio por chamadas do Sistema ou por Page Fault do Thread em execução. Eficiência obtida evitando transições desnecessárias entre os espaços do usuário e o do núcleo. Núcleo atribui processadores virtuais para cada processo. Deixa o sistema supervisor (no espaço do usuário) alocar threads para processadores (pode ser utilizado em sistemas multiprocessadores, trocando as CPU´s virtuais por CPU´s reais) Problema: Baseia-se fundamentalmente em Upcalls - o núcleo (camada inferior - n) chamando procedimentos no espaço do usuário (camada superior – n+1). Este comportamento viola a estrutura de independência entre camadas (Camada n oferece serviços a serem chamados pela camada n+1, mas a camada n não pode chamar serviços da camada n+1). Uteis em sistemas distribuídos. A abordagem tradicional seria bloquear um processo ou Thread aguardando a chegada de uma mensagem. Ao chegar a mensagem, o Thread bloqueado recebe o seu conteúdo, o examina e o processa. Na abordagem Thread Pop-Up, a chegada de uma mensagem cria um novo Thread para tratar a mensagem. Como são novos Threads, não possuem história (registradores, pilha, etc.) a ser restaurada, permitindo que sejam criados rapidamente, fazendo com que a latência entre a chegada da mensagem e o inicio do processamento seja baixa. Problema: Threads de Núcleo são mais fáceis de serem criados e mais rápidos, porem se tiverem problemas, são potencialmente mais perigosos do que os Threads de Usuário (p.e.: causar a perda de mensagens caso a CPU demore a responder e não libera para outro Thread) Criação de um novo thread quando chega uma mensagem (a) antes da mensagem chegar (b) depois da mensagem chegar Threads Pop-Up Muitos programas foram desenvolvidos em código Monothread e precisam ser convertidos para código Multithread, o que nem sempre é simples em razão de parâmetros, variáveis locais e variáveis globais. Dados que são utilizadas por um Thread passam a ser compartilhadas entre diversos Threads. Como evitar conflitos entre as Threads? Proibir o uso de variáveis globais? Exemplo da variável erno (Unix) (Código de erro em falha do sistema) Conflitos entre Threads sobre o uso de uma variável global Ex. Errno – UNIX Convertendo Monothread x Multithread Como evitar conflitos entre as Threads? Proibir o uso de variáveis globais? Não! Criar um tipo intermediário: Variáveis Globais Privadas, isolando as várias Globais especificas para cada Threads. Porém trata-se de algo complexo pois a maioria das linguagens de programação expressam variáveis Locais e Globais e não uma outra forma intermediária (Contornar através de alocação de “pedaços de memória” com ponteiros sendo passados para as Threads necessárias) Threads podem ter váriaveis globais individuais Convertendo Monothread x Multithread Convertendo Monothread x Multithread Rotinas de Bibliotecas não Reentrantes: Significa que as rotinas não foram projetadas para que se possa fazer uma segunda chamada a qualquer rotina enquanto uma chamada anterior ainda não tenha terminado. Risco de um Thread sobrepor dados de outro Thread. Soluçãopossível: Fornecer a cada rotina uma proteção que altera um bit para indicar que a biblioteca esta em uso. Assim qualquer tentativa de outro Thread usar uma rotina da biblioteca enquanto uma chamada anterior não for concluída, será bloqueada. Isso porem elimina grande parte do paralelismo potencial. Sinais de Interrupção: Não são específicos de cada Thread. Quem deverá captura- los? Como serão tratados? Por exemplo, um CTRL-C pode significar interromper o processo para um Thread e outro significado para outro Thread. Gerenciamento de Pilhas: Em especial situações de estouro de pilha “Stack fault”. O Núcleo pode não perceber a necessidade de crescer a pilha de um Thread e assim ocorrer o erro. Dificuldades não são insuperáveis mas demonstram que a introdução de Threads em um sistema não funcionará sem um bom re-projeto. OBRIGADO!
Compartilhar