Você está na página 1de 28

Threads ou Processos Leves

■ Sistemas Operacionais Tradicionais

Legenda:

■ Sistemas com Multithreading processo

thread

Contador de
programa

Programação Distribuída - Thais Batista - 2000


Threads

■ Processos que compartilham espaço de


endereçamento:

P1 P2 P3
threads P11, P12 thread P21 threads P31, P32, P33

Programação Distribuída - Thais Batista - 2000


Threads

■ Threads dentro de um processo são escalonadas e


executadas independentemente como se fossem
processos diferentes
■ Em Sistemas Multiprocessados diferentes threads
podem executar em diferentes processadores
■ Em Sistemas Monoprocessados threads devem ter
sua execução intercalada

Programação Distribuída - Thais Batista - 2000


Threads X Processos
■ Threads
– threads dentro de um mesmo processo compartilham o
mesmo espaço de endereçamento
– comunicação entre threads de um mesmo processo:
memória compartilhada
■ Processos:
– nada compartilham entre si.
– tempo de chaveamento de contexto entre processos é
alto
– espaço de endereçamento protegido => comunicação
entre processos: socket, pipes

Programação Distribuída - Thais Batista - 2000


Threads X Processos
Itens por Thread Itens por Processo
Contador de Programa Espaço de Endereçamento
Pilha Arquivos abertos
Registradores Signals
Threads Filhas Processos Filhos
Estado Estado

Cuidado: Aplicações Multithread são difíceis de projetar.


É fácil para uma thread interferir no trabalho de outra pois
elas compartilham memória e outros recursos do processo.
Programação Distribuída - Thais Batista - 2000
Necessidade de Threads

■ Permitir paralelismo dentro de um processo

■ Programação Concorrente torna-se mais fácil

■ Menor Tempo de Resposta

Programação Distribuída - Thais Batista - 2000


Benefícios de Threads
■ Throughput (capacidade de processamento)
– um sistema multithreaded pode aproveitar melhor a
capacidade de processamento da máquina
– ex.: uma thread espera resposta de uma solicitação de
entrada e saída enquanto outra thread está executando
outra função (overlap I/O)
■ Múltiplos processadores
– múltiplas threads oferecem uma maneira eficiente para
se explorar o paralelismo de hardware
– ex.: multiplicação de matrizes

Programação Distribuída - Thais Batista - 2000


Benefícios de Threads
■ Interface com Usuário
– aplicações de interface gráfica com usuário que executam
com única thread tipicamente exibe um cursor de espera (ou
relógio de tempo) e paraliza a interface enquanto a operação
é realizada.
– Se tal aplicação for multithreaded, enquanto uma thread está
realizando a operação solicitada, outra thread fica
monitorando a interface.
■ Evitar Deadlock
– servidores multithreaded podem criar uma thread para cada
solicitação recebida evitando que solicitações pendentes
causem deadlock

Programação Distribuída - Thais Batista - 2000


Exemplos do uso de Threads
■ Possibilita RPC simultâneas
■ Evita as paradas temporárias da janela de uma
Interface Gráfica durante a realização de uma
operação
■ Permite operações em background
■ Elimina a necessidade de interrupções a nível
do usuário. Uma thread pode ser dedicada
inteiramente à esperar a sinalização

Programação Distribuída - Thais Batista - 2000


Exemplo
■ Uma aplicação que mostra figuras descompactadas a
partir de uma série de arquivos.
– Com uma única thread: o programa descompacta a figura
do arquivo, mostra-a e espera que o usuário sinalize que
terminou de vê-la. O programa repete o processo para o
próximo arquivo.
– Com Multithread: usa-se uma thread para descompactar a
próxima figura enquanto o usuário está vendo a figura
corrente. Isto elimina o tempo de espera pelo processo de
descompactação.

Programação Distribuída - Thais Batista - 2000


Exemplo
Sem Threads
Descompactar N Exibir N

Arquivos
próximo

Com Threads

Descompactar N+1

Arquivos
Exibir N

próximo
Programação Distribuída - Thais Batista - 2000
#include <pthread.h>
int main (int argc, char *argv[])
{
pthread_t pic_thread;
int fileno;
pic_buf_t *buf;
for (fileno = 1; fileno < argc; fileno++) {
if (fileno == 1) { /* primeiro arquivo */
buf = get_next_picture((void *)argv[fileno]);
} else { /* espera que a thread de descompactação termine */
pthread_join(pic_thread, (void **)&buf);
}
if (fileno < argc - 1) {
/* dispara a thread para pegar a próxima figura (se houver) */
pthread_create(&pic_thread, NULL,
get_next_picture, (void *)argv[fileno + 1]);
}
display_buf(buf); /* mostra a figura corrente */
free(buf);
if (getchar() == EOF) /* espera que o usuário termine de olhar */
break;
}
return(0);
}
void *
get_next_picture(void * arg)
{
int fd;
pic_buf_t * buf;

fd = open((char *) arg, O_RDONLY);


if (fd < 0)
return(NULL);
buf = (pic_buf_t *) malloc(...)
while ((nbytes = read(fd,...)) != 0) {
descompacta_dados_e_coloca_no_buffer;
}
close (fd);
}
Sincronização entre Threads

■ Threads que cooperam para realizar


algumas atividades podem interferir uma na
outra já que elas acessam a mesma memória
■ Exemplo: Duas Threads que realizam
operações sobre a mesma conta_corrente

Programação Distribuída - Thais Batista - 2000


Código
Struct contas{
int conta_corrente;
int poupanca;
};
void poup_para_contacorr(struct contas *c, int valor)
{
c->poupanca -= valor;
c->conta_corrente += valor;
}

int total_balanco(struct contas *c)


{
int balanco;
balanco = c->conta_corrente + c->poupanca;
return(balanco);
}
Programação Distribuída - Thais Batista - 2000
Threads Concorrentes
Thread 1 chama total_balanco e Thread 2 chama poup_para_contacorr
os eventos ilustrados na figura abaixo podem ocorrer e, fazer com que o
valor retornado por total_balanco seja menor que a quantidade total de
dinheiro nas contas
Thread 1 Thread 2
T1 poupanca -= valor;
T2 balanco = poupanca + conta_corrente;
T3 conta_Corrente += valor;
T4 return(balanco);

Programação Distribuída - Thais Batista - 2000


Usando Semáforos
Struct contas{
int conta_corrente;
int poupanca;
};
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
void poup_para_contacorr(struct contas *c, int valor)
{
pthread_mutex_lock(&lock);
c->poupanca -= valor;
c->conta_corrente += valor;
pthread_mutex_unlock(&lock);
}
int total_balanco(struct contas *c)
{
int balanco;
pthread_mutex_lock(&lock);
balanco = c->conta_corrente + c->poupanca;
pthread_mutex_unlock(&lock);
return(balanco);
}
Programação Distribuída - Thais Batista - 2000
Why Threads Are a Bad Idea
John Ousterhout
Sun Labs

Programação Distribuída - Thais Batista - 2000


Problemas

■ Difíceis de Programar
– Sincronização:
» Uso de locks para coordenar o acesso a dados
compartilhados
» Controle de locks é responsabilidade do
programador
• Possibilidade de Deadlock

■ Difíceis de Depurar

Programação Distribuída - Thais Batista - 2000


Problemas
■ Dificuldade em bom Desempenho
– Necessidade de Locks implica em baixa
concorrência
– Muitos locks aumentam a complexidade e
reduz o desempenho
■ Quebra da idéia de Abstração e
Modularidade
– Não há independência no Projeto dos Módulos
■ Baixa Portabilidade
Programação Distribuída - Thais Batista - 2000
Alternativa

■ Usar EVENTOS
– Na maioria dos casos que usam threads, eventos
são melhores
– Threads devem ser usadas apenas quando é
necessário concorrência verdadeira

Programação Distribuída - Thais Batista - 2000


Programação Baseada em
Eventos

■ Uma execução por vez (não há


concorrência)
■ Registra-se interesse em eventos (callbacks)
■ Um loop de eventos espera por eventos
chamados por handlers.
loop de
eventos

Handlers de eventos

Programação Distribuída - Thais Batista - 2000


Utilidade de Eventos

■ Interfaces com Usuário


– Um handler para cada eventos (pressionar
botão, chamar uma entrada no menu, etc)
– Handler também pode implementar
comportamento (delete, undo, move...)
■ Sistemas Distribuídos
– Um handler para cada origem de entradas (I/O,
Socket, etc)

Programação Distribuída - Thais Batista - 2000


Exemplo do uso de Eventos
Interfaces com Usuário

Programação Distribuída - Thais Batista - 2000


Exemplo do uso de Eventos
Interfaces com Usuário

button_iniciar = xv_create(PanelConsulta, PANEL_BUTTON,


PANEL_LABEL_STRING, "Iniciar",
PANEL_NOTIFY_PROC, procurar,
NULL);
button_desistir = xv_create(PanelConsulta, PANEL_BUTTON,
PANEL_LABEL_STRING, "Desistir",
PANEL_NOTIFY_PROC, desistir,
NULL);

Programação Distribuída - Thais Batista - 2000


Problemas com Eventos

■ Não oferece concorrência


■ Nem sempre é possível fazer I/O usando
eventos (depende da capacidade de
buferização)
■ Problema com gerenciamento de
informações compartilhadas entre eventos
■ Muitos handlers implicam complexidade na
aplicação
Programação Distribuída - Thais Batista - 2000
Vantagens de Eventos

■ Facilidade de Programar com Eventos


■ Depuração mais fácil do que com Threads
■ Não ocasiona problemas de deadlock
■ Mais rápido que Threads em
monoprocessador (não precisa de troca de
contexto)
■ Mais portáveis que Threads

Programação Distribuída - Thais Batista - 2000


Deve-se Abandonar Threads?

■ NÃO!
■ Importante quando há concorrência
■ Deve-se evitar Threads sempre que
possível:
– para interfaces
– para sistemas distribuídos

Programação Distribuída - Thais Batista - 2000

Você também pode gostar