Upload
internet
View
105
Download
0
Embed Size (px)
Citation preview
Threads
Walfredo [email protected]
Memória Compartilhada
Uma questão básica em computação paralela é como as tarefas se comunicamUma alternativa é que as várias tarefas compartilhem a mesma memóriaNeste caso, as tarefas podem ser implementadas como processos ou threads
Processos Threads
Processos executam em espaço de endereçamento próprio, de modo a evitar interferência de outros processos Threads de um processo usam o mesmo espaço de endereçamentoThreads são mais “leves” que processos Além do que, pode-se criar threads a nível
de usuário (green threads)
Processos[possível criação de seg. memória
compartilhada]ppid = fork(); if (ppid < 0) {
fork_error_function(); } else if (ppid == 0) {
child_function(); } else {
parent_function(); }
Threads
Threads de um processo usam o mesmo espaço de endereçamentoO programador e a linguagem devem prover proteção contra interferênciasAlgumas linguagens possuem modelo de concorrência próprio (ex: ADA e Java)Outras linguagens utilizam extensões para lidar com threads (ex: C tipicamente usa Posix)
POSIX
POSIX: portable operating system interface Objetivo: Portabilidade do código fonte quando serviços do sistema operacional se fazem necessáriosPadrão IEEE
Aplicabilidade de Threads
Threads são muito úteis para paralelismo de “pequena escala” I/O não blocado Interface com o usuário Construção de servidores
Threads também são úteis em sistemas de tempo real, onde a concorrência é intrinseca ao problema
Modelo de Programação
Um modelo de programação paralelo deve implementar três primitivas básicas Criação de processos/threads Sincronização de processos Comunicação entre processos
Em memória compartilhada, a comunicação é feita pela própria memória
Necessidade de Sincronização
Por exemplo, considere dois processos atualizando uma variável comum: x = x + 1
Operações: Carregar x em um registro Incrementar registro Armazenar registro em x
C + Posix: Criação de Threads
Criação de thread via:int pthread_create ( pthread_t *thread_id,
const pthread_attr_t *attributes,void *(*thread_function)(void *),
void *arguments ); Termino quando função termina ou via:
int pthread_exit (void *status);
Um thread pode esperar por outro via:int pthread_join (pthread_t thread, void **status_ptr);
Semáforo
Semáforo S: variável não-negativa inteira que só pode se modificada pelos procedimentos up() e down()down(S) se S > 0: decremente Ssenão: bloqueia esperando up(S)up(S) se há alguém bloqueado: desbloqueie senão: incremente S
Exemplo de Semáforo
thread P2; statement A; down(mutex); statement B; up(mutex); statement C;end P2;
thread P1; statement X down(mutex); statement Y up(mutex); statement Zend P1;
(* exclusão mútua *)var mutex: semaphore := 1;
Mutex Posix
Mutex é um semáforo binário down() é chamado de lock() up() é chamado de unlock()
Posix tem as seguintes operações:int pthread_mutex_init (pthread_mutex_t *mut,
const pthread_mutexattr_t *attr); int pthread_mutex_lock (pthread_mutex_t *mut); int pthread_mutex_unlock (pthread_mutex_t *mut); int pthread_mutex_trylock (pthread_mutex_t *mut); int pthread_mutex_destroy (pthread_mutex_t *mut);
Condições
Mutex servem para proteção de regiões críticasAlém disso, precisamos esperar que outro thread faça alguma coisaResolvido em Posix através de condições
Condições Posixint pthread_cond_init (pthread_cond_t *cond,
pthread_condattr_t *attr); int pthread_cond_wait (pthread_cond_t *cond,
pthread_mutex_t *mut); int pthread_cond_signal (pthread_cond_t *cond); int pthread_cond_broadcast (pthread_cond_t *cond); int pthread_cond_timedwait (pthread_cond_t *cond,
pthread_mutex_t *mut, const struct timespec *abstime);
int pthread_cond_destroy (pthread_cond_t *cond);
Exemplo Posix
Produtor/Consumidor retirado de www.uq.edu.au/~cmamuys/humbug/talks/pthreads/pthreads.html
Monitores
Lidar com mutexes e condições é muito baixo nível e muito sujeito a errosMonitores encapsulam seções críticas como procedimentos de um modulo, sendo portanto muito mais fáceis de programar Todas as chamadas ao procedimentos são
executadas sob exclusão mútua Estruturas de sincronização estão
embutidas no monitor
Threads Java
Java tem monitores “orientados a objeto”Em Java, existe um lock associado a cada objeto que não pode ser acessado diretamente pela aplicaçãoQuando um método é identificado como synchronized, o acesso e feito apenas quando o lock associado com o objeto é obtido
Criando Threads em Java [1]public class SimpleThread extends Thread {
public SimpleThread(String str) {super(str);
}public void run() {
[ código do thread ]}
}
Criando Threads em Java [2]public class C extends D implements Runnable {
private Thread thread = null; public void start() {
if (clockThread == null) { thread = new Thread(this, “CThread");thread.start();
} } public void run() {
[código do thread ]}
}
Exclusão Mútua em Javaclass SharedInteger { private int theData; public SharedInteger(int initialValue) { theData = initialValue; } public synchronized int read() { return theData; } public synchronized void write(int newValue) { theData = newValue; }}
Sincronização em Java
Java associa condições a cada objetowait() espera pela condição do objetonotify() e notifyAll() acordam threads esperando pela condição
Exemplo Java
Produtor/Consumidor retirado de java.sun.com/docs/books/tutorial/essential/threads ProducerConsumerTest.java CubbyHole.java Producer.java Consumer.java
Agradecimentos
A Fabricio Silva que gentilmente nos forneceu seu material sobre tempo real, usados como base destas transparências