Escolar Documentos
Profissional Documentos
Cultura Documentos
GerênciaDeProcessos Resumo Gabrielle
GerênciaDeProcessos Resumo Gabrielle
Modelos de Geração de
Bibliotecas de threads
Multithreads
Uma biblioteca de threads fornece ao
O suporte aos threads pode ser: programador uma API para criação e
no nível do usuário (threads de gerenciamento de threads. Há duas maneiras
usuário): suportados acima do principais de implementá-las: Primeiro,
kernel e gerenciados sem o suporte fornecer uma biblioteca inteiramente no
do kernel. espaço do usuário sem suporte do kernel, em
ou pelo kernel (threads de kernel): que todo o código e estrutura de dados dela
Suportados e gerenciados estão no espaço do usuário. A segunda forma
diretamente pelo SO. é a implementação de um biblioteca no nível
Deve existir um relacionamento entre do kernel com suporte direto do SO.
os dois tipos acima. Três bibliotecas de threads principais
são usadas atualmente: a Pthreads do POSIX,
Modelos MuitosParaUm a do Windows e a de Java.
Duas estratégias gerais para a criação
Mapeia muitos threads de nível de de múltiplos threads é a síncrona e assíncrona.
usuário para um thread de kernel. Na criação de threads assíncrona,
O gerenciamento dos threads é feito cada thread é executado de forma
no espaço do usuário, sendo eficiente. independente e o pai não precisa saber
Todo o processo pode ser bloqueado quando o filho terminou. Geralmente há
se um thread fizer uma chamada de sistema pouco compartilhamento de dados entre
bloqueadora. eles.
Na criação de threads síncrona, o pai
Modelo UmParaUm precisa esperar que todos os filhos terminem
para ele voltar a ser executado (estratégia
Mapeia cada thread de usuário para conhecida como forkjoin).
um thread de kernel.
Fornece mais concorrência que o
muitos-para-um.
Permite que múltiplos threads sejam Threading Implícito
executados em paralelo em
multiprocessadores. Com o crescimento do processamento
Desvantagem: a criação de um thread multicore, aplicações contendo muitas
de usuário requer a criação de um thread de threads estão surgindo, mas projetar essas
kernel. aplicações não é algo simples.
Uma forma de tornar isso mais simples é
Modelos MuitosParaMuitos transferindo a criação e o gerenciamento de
threads dos desenvolvedores para os
Multiplexa muitos threads de usuário compiladores e bibliotecas de tempo de
para um número menor ou igual de threads execução. Essa estratégia é chama de
de kernel. Threading Implícito. Há três alternativas para
Permite que o desenvolvedor crie os o projeto de programas multithreads que
quantos threads o usuário quiser, mas não tiram proveito de processadores multicore por
resulta em uma concorrência real, pois o meio do threading implícito.
Pool de Threads Se o thread em um programa chamar
fork ( ), o novo processo duplicará todos os
Criação de múltiplos threads na threads, ou o novo processo será um púnico
inicialização do processo, bem como a thread. Alguns sistemas UNIX têm duas versões
inserção dos threads em um pool, onde eles de fork ( ), uma para cada uma dessas
ficarão esperando para entrar em ação. opções.
Quando o serviço terminar a ação, ele Se um thread chamar exec ( ), o
retorna para o pool. Se o pool não tem thread programa especificado como parâmetro
disponível, ele espera. substituirá o processo inteiro – inclusive nos
Isso resolve o problema do gasto do UNIX, um sinal é usado para mostrar que
tempo de criação para threads, a falta ade determinado evento ocorreu. O sinal pode ser
aproveitamento dele depois e evita que os síncrono ou assíncrono e seguem o mesmo
recursos do sistema sejam exauridos. padrão:
Um sinal é gerado pela ocorrência
OpenMP de um evento específico.
O sinal é liberado para um
Conjunto de diretivas de computação processo.
assim como uma API para programas escritos Uma vez liberado, ele deve ser
em C, C++ ou FORTRAN. manipulado.
Ele identifica regiões paralelas como Dois manipuladores possíveis de sinais:
blocos de códigos que podem ser Um manipulado default.
executados em paralelo, permite que os Um manipulador definido pelo
desenvolvedores escolham entre vários níveis usuário.
de paralelismo e permite que os Para onde o sinal deve ser liberado:
desenvolvedores identifiquem se os dados Para o thread ao qual ele é
são compartilhados entre threads ou se são aplicável.
privados de um thread. Para cada thread do processo
Para certos threads do processo
Grand Central Dispatch Designar um thread específico para
receber todos os sinais do processo.
Também chamado de GCD é uma
tecnologia para SOs Mac OS X e IOS da Cancelamento de Threads
Apple. Ele é uma combinação de extensões
para a linguagem C, uma API e uma Envolve o encerramento de um thread
biblioteca de tempo de execução que antes de ele ser concluído.
permite aos desenvolvedores de aplicações Um thread a ser cancelado é
identificarem seções de códigos a serem chamado de thread-alvo.
executados em paralelo. O cancelamento pode ocorrer em dois
cenários:
Outras Abordagens Cancelamento assíncrono: thread
encerrado imediatamente.
Incluem bibliotecas paralelas e Geralmente o SO reclama os
concorrentes, como Threading Building Blocks recursos do thread cancelado, mas
(TBB) da Intel e vários produtos da Microsoft. não todos.
Cancelamento adiado. É o
cancelamento default
Questões Relacionadas com a
Armazenamento Local do Thread
Criação de Threads
Algumas vezes, cada thread pode
Chamadas de Sistema Fork() e Exec() precisar de sua própria cópia de certos dados
(esses dados são chamados de
A chamada de sistema fork ( ) é usada armazenamento local do thread ou TLS)
para criar um processo duplicado separado. As variáveis locais são visíveis apenas
A semântica dessas chamadas muda durante uma única invocação de função,
em um programa com múltiplos threads. enquanto os dados TLS são visíveis ao longo
das invocações de funções. A diferença é
que os dados TLS são únicos para cada executado em modalidade de
thread. kernel.
Área de armazenamento privada
Ativação do Scheduler usada para várias bibliotecas de
tempo de execução e bibliotecas
Muitos sistemas que implementam o de links dinâmicos (DLLs).
modelo muito-para-muitos ou de dois níveis O conjunto de registradores, as pilhas e
inserem uma estrutura de dados as áreas de armazenamento são chamadas
(normalmente conhecida como peso leve ou de contextos do thread.
LWP) intermediária entre os threads do usuário Principais estruturas de dados de uma
e do kernel. thread:
Para a biblioteca de threads do ETHREAD – bloco de thread
usuário, o LWP aparece como um exclusivo.
processador virtual em que a aplicação pode KTHREAD – bloco de thread do
incluir no schedule um thread de usuário para kernel.
execução. Cada LWP é anexado a um TEB – bloco de ambiente do thread.
thread do kernel que o SO inclui no schedule
para execução em processadores físicos. Se Threads no Linux
um thread do kernel for bloqueado o LWP
também será. Fornece a chamada fork ( ) com a
Uma aplicação pode requerer funcionalidade tradicional de duplicar um
quantos LWPs quiser para ser executada processo. Fornece também a chamada
eficientemente. clone ( ) para criar threads. No entanto, o
A ativação do schedule é usada para Linux não diferencia processos e threads. Ele
a comunicação entre a biblioteca de threads usa o termo tarefa ao se referir a um fluxo de
de usuário e o kernel. Nele, o kernel fornece controle dentro de um programa.
uma aplicação um conjunto de
processadores virtuais (LWPs), e a aplicação
pode incluir no schedule threads de usuário Antecedentes
para um processador virtual disponível. Além
disso, o kernel deve informar a aplicação Uma situação em que vários processos
sobre certo eventos (procedimento acessam e manipulam os mesmos dados e o
chamado de upcall). As upcalls são concorrentemente e o resultado depende da
manipuladas pela biblioteca de threads com ordem em que processo ocorre é chamada
um manipulador de upcalls que deve ser de uma condição de corrida. Para saber a
executado em um processador virtual. ordem, é necessária alguma forma de
sincronização.
Erros de timing podem ocorrer ao usar Uma solução para determinar qual dos
semáforos. Para lidar com eles, pesquisadores processos suspensos deve ser retomado é usar
desenvolveram construtores de linguagem de a ordem FCFS (primeiro a entrar, primeiro a ser
alto nível. Nesse caso, será mostrado o atendido), para que o processo que tenha
monitor. esperado mais tempo seja retomado
primeiro. Em muitas circunstâncias um
Uso esquema de Scheduling tão simples não é
adequado. Por isso, o construtor de espera
Um tipo de dados abstrato (ADT) condicional pode ser usado.
encapsula dados com um conjunto de O conceito de monitor não garante
funções para operarem sobre esses dados, que a sequência de acesso anterior seja
que são independentes de qualquer seguida.
implementação específica do ADT. Problemas que podem ocorrer:
Um tipo monitor é um ADT que inclui um Um processo pode acessar um
conjunto de operações – definidas pelo recurso sem antes obter permissão
programador – e que são de exclusão mútua para isso.
dentro do monitor. Ele também declara Um processo pode nunca liberar
variáveis cujo valores definem o estado de um recurso após ter acesso a ele.
uma instância desse tipo, além dos corpos de Um processo pode tentar liberar um
funções que operam sobre essas variáveis. recurso que nunca solicitou.
Um processo pode solicitar o que uma variável inteira precisa ser
mesmo recurso duas vezes, sem atualizada, já que essas operações inteiras
liberá-lo antes. não geram overhead dos lockings. Há
também os lock mutex, para proteger seções
críticas. Usa-se ainda de spinlocks e
Exemplos de Sincronização semáforos.
Em uniprocessadores: a preempção
No Windows do kernel é desativada.
Em multiprocessadores: a preempção
O Windows é um kernel multithread e é ativada.
dá suporte a aplicações de tempo real e a Os spinlocks são usados no kernel
múltiplos processadores. apenas quando um lock é mantido por um
Em um sistema uniprocessado, quando curto tempo. Quando um lock precisa ser
o kernel acessa um recurso global, as mantido por mais tempo, o mais adequado é
interrupções são mascaradas o semáforo ou locks mutex.
temporariamente.
Em sistemas multiprocessados, ele No Solaris
protege o acesso a recursos globais usando
spinlocks. Além disso, o kernel assegura que Fornece locks mutex adaptativos,
uma thread nunca sofra preempção variáveis de condição, semáforos, locks de
enquanto estiver mantendo um spinlocks. leitor-gravador e roletas.
Para a sincronização de threads fora Um mutex adaptativo protege o
do kernel, o Windows oferece objetos acesso a todos os itens de dados críticos. No
despachantes, em que os threads são Solaris ele é usado para proteger apenas os
sincronizados de acordo vários mecanismos dados que são acessados por curtos
diferentes, como locks mutex, semáforos, segmentos de código.
eventos e timers. Os locks de leitor-gravador são usados
Os objetos despachantes podem estar para proteger dados que são acessados
em: frequentemente, mas que são de somente
Estado sinalizado: o objeto está leitura.
disponível e o thread não será bloqueado ao Usa roletas para ordenar a lista de
adquiri-lo. threads em espera para adquirir um mutex
Estado não sinalizado: Objeto não adaptativo ou locks de leitor-gravador.
disponível, e o thread será bloqueado ao Roleta é uma estrutura de fila que
tentar adquiri-lo. contém os threads trancados de um lock.
Um objeto seção crítica é um mutex de
modalidade de usuário que pode ser
adquirido e liberado sem intervenção do Abordagens Alternativas
kernel. Em sistemas multiprocessado, ele usa
primeiro um spinlocks enquanto espera que o À medida que o número de núcleos de
outro thread libere o objeto. Se ele mantiver o processamento aumenta, torna-se cada vez
spin por muito tempo, o thread que está mais difícil projetar aplicações multithreads
tentando obter o objeto alocará então um que não apresentem condições de corrida e
mutex do kernel e abandonará sua CPU. deadlocks.
Antes da versão 2.6, o Linux era um Seu conceito teve origem na teoria de
kernel sem preempção. banco de dados, e mesmo assim, é uma
Agora, ele é totalmente preemptível e, estratégia para sincronização de processos.
uma tarefa pode sofrer preempção quando Uma transação de memória é uma
está sendo executada no kernel. sequência de operações atômicas de leitura-
Ele fornece vários mecanismos gravação em memória. Se todas as
diferentes para a sincronização do kernel. A operações de uma transação são
mais simples é um inteiro atômico. Estes são concluídas, a transação da memória é
particularmente eficientes em situações em confirmada. Caso contrário, as operações
são abortadas e revertidas. Os benefícios da
memória transacional podem ser obtidos por
recursos adicionados a uma linguagem de
programação.
A vantagem desse mecanismo no
lugar dos locks é o que o sistema transacional
– e não o desenvolvedor – é responsável por
garantir a atomicidade. Não é possível a
ocorrência de deadlocks.
A memória transacional pode ser
implementada em software (memória
transacional em software – STM) e hardware
(memória transicional em hardware – HTM)
OpenMP