Threads Walfredo Cirne walfredo@dsc.ufcg.edu.br. Memória Compartilhada Uma questão básica em...

Preview:

Citation preview

Threads

Walfredo Cirnewalfredo@dsc.ufcg.edu.br

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

Recommended