CAPÍTULO VI – THREADS 6.1 INTRODUÇÃO • Até o final de década de 70, os sistemas operacionais suportavam apenas processos com um único thread; • O sistema operacional Toth, em 1979, foi o primeiro a implementar o conceito de thread. Porém, comercialmente, o primeiro sistema operacional a suportar threads foi o Mach, em 1980; • O conceito de múltiplos threads ( multithread ) permitiu projetar e implementar aplicações concorrentes de forma eficiente, pois um processo pode ter partes diferentes do seu código sendo executadas em paralelo; • Threads aumentam o desempenho da aplicação pois não envolvem mecanismos lentos de intercomunicação, já que compartilham o mesmo espaço de endereçamento. 6.2 AMBIENTE MONOTHREAD • Um processo suporta apenas um programa no seu espaço de endereçamento; • Implementa aplicações concorrentes com o uso de múltiplos processos independentes ou subprocessos. • O problema deste tipo de implementação é que o uso de processos no desenvolvimento de aplicações concorrentes demanda consumo de diversos recursos do sistema; • Outro problema é o compartilhamento do espaço de endereçamento. Como cada processo possui o seu próprio espaço, a comunicação entre processos torna-se lenta e difícil, pois utiliza mecanismos como pipes, sinais, semáforos, memória compartilhada ou troca de mensagem. • O compartilhamento de recursos comuns aos processos concorrentes, como memória e arquivos abertos, também não é simples. • Exemplos de sistemas operacionais monothread: MS-DOS, primeiras versões do Microsoft Windows e versões antigas do UNIX. 6.3 AMBIENTE MULTITHREAD • Programas não são associados a processos, mas sim, a threads; • Um processo tem pelo menos uma thread em execução, todavia, pode compartilhar seu espaço de endereçamento com inúmeras threads; • Uma thread pode ser definida como uma sub-rotina de um programa que pode ser executada de forma assíncrona, ou seja, executada paralelamente ao programa chamador; • Threads compartilham o processador da mesma forma que processos e passam pelas mesmas mudanças de estado; • Cada thread possui seu próprio contexto de hardware, porém, dentro de um mesmo processo, compartilham seus contextos de software e espaço de endereçamento. • Threads são implementadas através de uma estrutura de dados denominada Thread Control Block ( TCB ); • Como todas as threads de um processo acessam um mesmo espaço de endereçamento, não há qualquer proteção à memória, permitindo que uma thread altere dados de outras. Para que threads trabalhem de forma cooperativa, é fundamental que a aplicação implemente mecanismos de comunicação e sincronização entre threads, a fim de garantir o acesso seguro aos dados compartilhados na memória; • A utilização de threads pode melhorar o desempenho da aplicação executando tarefas em background enquanto operações E/S estão sendo processadas; • Em ambientes cliente-servidor, threads são essenciais para solicitações de serviços remotos; • O próprio núcleo do sistema operacional pode fazer uso do multithreading. Por exemplo, na arquitetura microkernel. 6.4 ARQUITETURA E IMPLEMENTAÇÃO • Pacote de threads é o conjunto de rotinas disponíveis para que uma aplicação utilize as facilidades dos threads; • Um pacote de threads pode ser implementado sob diversas abordagens em um sistema operacional, o que influi diretamente no desempenho, na concorrência e na modularidade das aplicações multithread; • Threads podem ser oferecidas por uma biblioteca de rotinas fora do núcleo do sistema operacional ( modo usuário ), pelo próprio núcleo do sistema ( modo Kernel ), por uma combinação de ambos ( modo híbrido ) ou por um modelo conhecido como Scheduler Activations; 6.4.1 THREADS EM MODO USUÁRIO ( TMU ) • São implementadas pela aplicação e não pelo sistema operacional; • O sistema operacional não sabe da existência de múltiplas threads, sendo responsabilidade exclusiva da aplicação gerenciar e sincronizar os diversos threads existentes. VANTAGENS: • Permitem a implementação de threads mesmo em sistemas operacionais que não suportam threads; • São rápidos e eficientes por dispensarem o acesso ao kernel do sistema; DESVANTAGENS • O sistema operacional gerencia o processo como se houvesse uma única thread. Quando uma thread chama uma rotina do sistema que o coloca em estado de espera, todo o processo é colocado em estado de espera, mesmo havendo outras threads prontas para execução; • Tratamento individual de sinais. Como o sistema operacional reconhece apenas processos e não threads, os sinais enviados para um processo devem ser reconhecidos e encaminhados a cada thread para tratamento; • Redução do grau de paralelismo. Não é possível que múltiplos threads possam ser executados em diferentes UCP’s simultaneamente. O sistema seleciona apenas processos para execução e threads de um processo podem ser executadas somente em um processador de cada vez. 6.4.2 THREADS EM MODO KERNEL ( TMK ) • São implementadas diretamente pelo núcleo do sistema operacional; VANTAGENS: • O sistema operacional sabe da existência de cada thread e pode escaloná-las individualmente; • Caso haja múltiplos processadores, threads de um mesmo processo podem ser executadas simultaneamente; DESVANTAGENS: • Baixo desempenho. Enquanto nos pacotes em modo usuário todo o tratamento é feito sem a ajuda no sistema operacional, no modo kernel são utilizadas chamadas a rotinas do sistema e, conseqüentemente, há várias mudanças no modo de acesso; 6.4.3 THREADS EM MODO HÍBRIDO • Combina vantagens de threads implementadas em modo usuário ( TMU ) e threads em modo Kernel ( TMK ); • Um processo pode ter vários TMK e, por sua vez, um TMK pode ter vários TMU; • Um TMU pode ser executado em um TMK e, em um instante seguinte, ser executado em outro; VANTAGENS • Maior flexibilidade DESVANTAGENS: • Apresenta problemas herdados de ambas implementações. Por exemplo, uma chamada de bloqueio de uma TMK bloqueia todos os TMU, que são colocados em espera; • TMU’s que precisam utilizar diferentes processadores precisam utilizar diferentes TMK, o que reduz o desempenho. 6.4.4 SCHEDULER ACTIVATIONS • Os problemas apresentados no pacote de threads em modo híbrido existem devido à falta de comunicação entre os threads em modo usuário e modo kernel; • Usa o melhor do modo usuário e do modo kernel, através de uma estrutura de dados chamada scheduler activations; • Alcança um melhor desempenho evitando mudanças de modos de acesso que não sejam necessárias; • Caso uma thread utilize uma chamada ao sistema que o coloque no estado de espera, não é necessário que o kernel seja ativado, basta que a própria biblioteca escalone outra thread; • Bibliotecas em modo usuário e kernel se comunicam, trabalhando de forma cooperativa; 6.5 MODELOS DE PROGRAMAÇÃO • O desenvolvimento de aplicações multithread não é simples, pois exige que a comunicação e o compartilhamento de recursos entre as diversas threads sejam feitos de forma sincronizada para evitar inconsistências e deadlock; • O número máximo de threads é um fator importante. Caso um número muito grande seja criado, poderá haver um overhead no sistema, ocasionando uma queda de desempenho; • O número de threads pode ser dinâmico ou estático; • Para permitir a implementação de threads, uma aplicação deve permitir que partes diferentes do seu código sejam executadas em paralelo, de forma independente. • Exemplos de aplicações de multithreading: o o SGBDs Servidores de arquivos ou impressão