Você está na página 1de 13

UNIVERSIDADE CATÓLICA DE ANGOLA

FACULDADE DE ENGENHARIA
ENGENHARIA INFORMÁTICA

THREADS

Turma: P
Cadeira: Sistemas Distribuidos e Paralelos I
Turno: Pós-Laboral
3º Ano

Docente:
________________

Luanda, 2024
UNIVERSIDADE CATÓLICA DE ANGOLA
FACULDADE DE ENGENHARIA
ENGENHARIA INFORMÁTICA

THREADS

Autor:
Duely Diantantu…………………………...…………………....28980
ÍNDICE

Resumo..........................................................................................3
Introdução......................................................................................4
O conceito de Threads...................................................................5
Características das Threads.......................................................5
Exemplo Prático:........................................................................5
Prioridades na Execução...............................................................6
Ciclo de Vida das Threads.............................................................7
Exemplo Prático:........................................................................7
Sincronização entre Threads.........................................................8
Exemplo Prático:........................................................................8
Dependências entre Threads.........................................................9
Exemplo Prático:........................................................................9
Vantagens e Desvantagens.........................................................10
Vantagens:...............................................................................10
Desvantagens:.........................................................................10
Boas Práticas...............................................................................11
Exemplo:..................................................................................11
Conclusão....................................................................................12
Resumo

Este trabalho explora o conceito de threads em programação,


abordando suas características, prioridades de execução, ciclo de
vida, sincronização e dependências entre threads. Inicialmente, são
apresentadas as definições fundamentais de threads e suas
principais características. Em seguida, discute-se a importância das
prioridades na execução das threads, bem como os diferentes
estados que uma thread pode assumir ao longo de seu ciclo de
vida. Além disso, são exploradas técnicas de sincronização para
garantir a consistência e a ordem de execução entre threads, assim
como as dependências que podem surgir entre elas. Por meio de
exemplos práticos, são ilustradas as vantagens e desvantagens do
uso de threads, destacando-se boas práticas para sua
implementação eficaz.

3 | Página
Introdução

Em ambientes de programação, especialmente em sistemas


operacionais e aplicações de software de alto desempenho, o
conceito de threads desempenha um papel preponderante. Uma
thread pode ser entendida como uma sequência de instruções que
podem ser executadas independentemente dentro de um processo.
Enquanto os processos são unidades de execução mais amplas, as
threads representam unidades de execução menores e mais leves,
capazes de compartilhar recursos com outras threads do mesmo
processo.
Este trabalho se propõe a explorar profundamente o conceito de
threads, examinando suas características fundamentais, prioridades
na execução, ciclo de vida, mecanismos de sincronização e
dependências entre threads. Ao longo do documento, serão
apresentados exemplos práticos para ilustrar os conceitos de
threads, bem como vantagens e desvantagens associadas ao uso
de threads em diferentes contextos. Além disso, serão abordadas
boas práticas para o desenvolvimento de sistemas que fazem uso
eficiente de threads, visando garantir desempenho, robustez e
escalabilidade.

4 | Página
O conceito de Threads
As threads são elementos dos processos que executam de forma
independente com as suas respectivas memórias e contador de
programa, desta forma, uma thread é identificada como unidades
independentes de um processo ou até mesmo como subprocessos
que executam varias tarefas para alcançar o objetivo do processo e
consequentemente do programa.
Características das Threads
As threads são unidades de execução leves dentro de um
processo, capazes de compartilhar recursos e executar tarefas de
forma concorrente. Uma das características mais interessantes das
threads é sua capacidade de compartilhar o mesmo espaço de
endereçamento com outras threads do mesmo processo. Isso
significa que as threads podem acessar variáveis e estruturas de
dados compartilhadas sem a necessidade de comunicação explícita
entre processos, simplificando a comunicação e a sincronização de
dados.
Além disso, as threads são mais leves que os processos
tradicionais, o que significa que têm um menor consumo de
recursos do sistema, incluindo memória e tempo de CPU. Isso torna
as threads ideais para situações em que é necessário um alto grau
de concorrência e paralelismo, como em servidores web, sistemas
de bancos de dados e jogos multiplayer online.
Outra característica importante das threads é sua capacidade de
execução concorrente. Isso significa que várias threads podem
executar simultaneamente em sistemas com múltiplos núcleos de
CPU, aumentando significativamente a eficiência e o desempenho
do sistema.
Exemplo Prático:
Considere um servidor web que precisa lidar com várias
solicitações de clientes simultaneamente. Cada solicitação pode ser
tratada por uma thread separada, permitindo que o servidor atenda
a múltiplos clientes ao mesmo tempo. Isso melhora
significativamente o tempo de resposta percebido pelos usuários e
a capacidade de escalabilidade do servidor.

5 | Página
Prioridades na Execução
A atribuição de prioridades às threads é importante para controlar
a ordem em que são executadas pelo escalonador do sistema
operacional. As threads com prioridades mais altas têm maior
probabilidade de serem executadas primeiro, enquanto as de
prioridades mais baixas podem ser adiadas em favor das mais
altas. Isso permite que os desenvolvedores controlem o
comportamento relativo das threads e priorizem a execução de
tarefas críticas.
É importante notar que a priorização de threads pode variar entre
diferentes sistemas operacionais e implementações de
programação, e que o uso excessivo de prioridades pode levar a
problemas de starvation, onde threads com prioridades mais baixas
não recebem tempo de CPU suficiente para executar suas tarefas.
As prioridades na execução das threads desempenham um papel
importante no comportamento e desempenho do sistema. No
entanto, é necessario observar que a manipulação incorrecta das
prioridades pode levar a problemas como inanição de recursos e
inversão de prioridade.
Inanição de Recursos: a inanição ocorre quando uma thread
com baixa prioridade nunca consegue acesso aos recursos do
sistema, pois as threads com prioridades mais altas sempre estão
em execução. Isso pode resultar em um comportamento injusto e
prejudicar o desempenho geral do sistema.
Inversão de Prioridade: a inversão de prioridade acontece
quando uma thread com prioridade mais alta é bloqueada por uma
operação realizada por uma thread com prioridade mais baixa. Isso
pode ocorrer em situações onde uma thread de alta prioridade
aguarda a conclusão de uma operação crítica que está sendo
realizada por uma thread de baixa prioridade.
Para mitigar esses problemas, é importante atribuir prioridades de
forma equilibrada e consciente, considerando os requisitos de
desempenho e a criticidade das tarefas executadas por cada
thread.

6 | Página
Ciclo de Vida das Threads
O ciclo de vida de uma thread passa pelos diferentes estados
dos quais desde sua criação até sua conclusão. Os principais
estados incluem:
 Pronto: a thread está pronta para ser executada, mas ainda
não recebeu tempo de CPU.
 Em Execução: a thread está atualmente em execução na
CPU.
 Bloqueado: a thread está temporariamente impedida de
executar devido à espera por algum evento externo, como E/S de
dados.
 Terminado: a thread concluiu sua execução e foi encerrada.
Entender o ciclo de vida das threads é essencial para gerenciar
seu comportamento e garantir uma execução adequada do
programa. Durante sua vida útil, uma thread pode alternar entre
esses estados à medida que executa suas tarefas e interage com
outros elementos do sistema.
Exemplo Prático:
Consideremos um sistema de reprodução de vídeo em que uma
thread é responsável pela decodificação de fluxos de vídeo e outra
pela reprodução dos quadros decodificados. Quando não há mais
dados para decodificar, a thread de decodificação entra no estado
bloqueado, aguardando a disponibilidade de mais dados. Enquanto
isso, a thread de reprodução continua funcionando, garantindo uma
experiência de reprodução contínua para o usuário.

7 | Página
Sincronização entre Threads
Em sistemas multi-threaded, é comum que as threads
compartilhem recursos e dados. No entanto, isso pode levar a
problemas de concorrência, onde duas ou mais threads tentam
acessar ou modificar o mesmo recurso simultaneamente, levando a
resultados inesperados ou inconsistências nos dados. Para evitar
tais problemas, técnicas de sincronização são utilizadas.
Mutexes: Um mutex (em português de "exclusão mútua") é uma
estrutura de dados que atua como um sinalizador para controlar o
acesso a um recurso compartilhado. Uma thread que deseja
acessar o recurso bloqueia o mutex antes de acessá-lo e o libera
após a conclusão. Isso garante que apenas uma thread por vez
tenha acesso ao recurso, evitando condições de corrida.
Semáforos: Um semáforo é um tipo de variável que é usada para
controlar o acesso concorrente a um recurso compartilhado. Ele
pode ter um valor inteiro não negativo, e as operações de
incremento e decremento são realizadas atomicamente. Os
semáforos são frequentemente usados para controlar o acesso a
um número fixo de recursos, como pools de threads ou buffers de
dados.
Variáveis de Condição: Uma variável de condição é usada para
sinalizar a ocorrência de um evento entre threads. Uma thread pode
esperar por um evento associado a uma variável de condição
usando a operação wait, e outras threads podem sinalizar a
ocorrência do evento usando a operação signal. Isso é útil em
situações em que uma thread precisa aguardar a conclusão de uma
operação por outra thread.
Exemplo Prático:
Considere um sistema de gerenciamento de arquivos que permite
a edição simultânea de um mesmo arquivo por múltiplos usuários.
Para evitar conflitos de escrita, um mutex pode ser usado para
garantir que apenas uma thread por vez tenha permissão para
escrever no arquivo. Dessa forma, as operações de escrita são
sincronizadas entre as threads, garantindo a consistência dos
dados.
8 | Página
Dependências entre Threads
Em muitos sistemas, as threads dependem umas das outras para
realizar determinadas tarefas ou alcançar certos objetivos. Por
exemplo, uma thread pode precisar esperar que outra termine de
processar dados antes de poder continuar sua própria execução.
Gerenciar essas dependências de forma eficiente é crucial para
garantir que as threads sejam executadas na ordem correta e que
os resultados sejam consistentes e precisos.
Sincronização de Dependências: Para lidar com dependências
entre threads, técnicas de sincronização são frequentemente
utilizadas. Isso pode incluir o uso de variáveis de condição,
semáforos ou mutexes para coordenar a execução de threads
dependentes. Além disso, estruturas de dados como filas e pilhas
podem ser empregadas para garantir a ordem de execução das
threads.
Exemplo Prático:
Suponha que em um sistema de processamento de imagens,
uma thread é responsável por carregar uma imagem do disco,
enquanto outra é responsável por aplicar filtros à imagem
carregada. A thread de aplicação de filtros precisa esperar até que
a imagem esteja completamente carregada antes de poder iniciar
seu trabalho. Para isso, pode-se utilizar uma variável de condição
para sinalizar a conclusão do carregamento da imagem e permitir
que a thread de aplicação de filtros comece a processar a imagem.
Outro exemplo prático de dependência entre threads é
encontrado em sistemas de produção e consumo, onde uma thread
produz dados que são consumidos por outra thread. A thread
consumidora deve esperar até que haja dados disponíveis para
consumo, e a thread produtora deve sinalizar quando novos dados
são produzidos. Isso pode ser implementado usando uma fila ou
buffer compartilhado entre as threads, onde a thread produtora
insere dados e a thread consumidora os retira.

9 | Página
Vantagens e Desvantagens
Vantagens:
 Melhoria do Desempenho: O uso de threads pode levar a
uma melhoria significativa no desempenho e na capacidade de
resposta de um sistema, especialmente em sistemas multi-core,
onde as threads podem ser executadas em paralelo.
 Utilização Eficiente de Recursos: As threads permitem uma
utilização mais eficiente dos recursos de hardware, como CPU e
memória, ao permitir que múltiplas tarefas sejam executadas
simultaneamente.
 Escalabilidade: O uso de threads pode facilitar a
escalabilidade de sistemas, permitindo que tarefas sejam divididas
e executadas em paralelo em múltiplos núcleos de CPU ou
máquinas distribuídas. Isso possibilita o aproveitamento máximo
dos recursos disponíveis e pode melhorar significativamente o
desempenho do sistema.
 Responsividade: Threads bem projetadas podem aumentar a
responsividade de sistemas interativos, permitindo que tarefas de
longa duração sejam executadas em segundo plano, enquanto a
interface do usuário permanece receptiva e interativa.

Desvantagens:
 Complexidade de Programação: O desenvolvimento de
sistemas multi-threaded pode ser mais complexo do que sistemas
single-threaded, devido à necessidade de lidar com problemas de
concorrência e sincronização entre threads.
 Depuração Difícil: Problemas de concorrência, como
condições de corrida e deadlocks, podem ser difíceis de depurar e
reproduzir, tornando o desenvolvimento e a manutenção de
sistemas multi-threaded mais desafiadores.
 Overhead: A criação e o gerenciamento de threads podem
introduzir overhead significativo no sistema, especialmente em
sistemas com muitas threads concorrentes. Isso pode resultar em

10 | P á g i n a
uma utilização ineficiente dos recursos do sistema e impactar
negativamente o desempenho geral.

Boas Práticas

 Evitar Excesso de Threads: Criar um grande número de


threads pode levar a sobrecarga no sistema devido ao alto consumo
de memória e tempo de CPU. É importante projetar sistemas com
um número adequado de threads para evitar esse problema.
 Projeto com Baixo Acoplamento: Projetar sistemas com
baixo acoplamento entre threads pode facilitar a manutenção e a
escalabilidade, permitindo que as threads sejam modificadas ou
substituídas independentemente umas das outras.
 Monitoramento e Perfis: O monitoramento e o perfil de
desempenho de sistemas multi-threaded são essenciais para
identificar gargalos de desempenho, problemas de concorrência e
oportunidades de otimização. Ferramentas e bibliotecas de profiling
podem ser utilizadas para analisar o comportamento e o
desempenho das threads em tempo real.
Exemplo:
No desenvolvimento de um servidor de aplicativos web altamente
escalável, é fu ndamental adotar técnicas de monitoramento e
perfil de desempenho para identificar gargalos de desempenho e
otimizar o uso de recursos. Ferramentas como o VisualVM e o
Apache JMeter podem ser usadas para analisar o comportamento e
o desempenho das threads em ambiente de produção e
desenvolvimento.

11 | P á g i n a
Conclusão
Neste trabalho, exploramos os conceitos fundamentais
relacionados às threads em programação, examinando suas
características, prioridades de execução, ciclo de vida,
sincronização e dependências entre threads. Ao longo do trabalho,
foram apresentados exemplos práticos, vantagens e desvantagens,
bem como boas práticas associadas ao uso eficiente.

12 | P á g i n a

Você também pode gostar