Sistemas Operacionais: Threads Threads • Única linha de execução x múltiplas linhas de execução Benefícios • • • • Tempo de resposta Compartilhamento de recursos Economia de recursos Desempenho em arquiteturas multiprocessadas Kernel x User-Level Threads • Kernel: suporte à Threads diretamente no sistema operacional • User: gerenciado por uma biblioteca que executa no nível do usuário • Exemplos de threads com suporte no kernel – – – – – Windows XP/2000 Solaris Linux Tru64 UNIX Mac OS X Mapeamento de threads • Mapeamento de threads do usuário e kernel – Muitos para um – Um para um – Muitos para muitos Muitos para um • Várias threads no nível do usuário, mapeadas para uma única thread no nível do kernel • Exemplos: – Solaris Green Threads – GNU Portable Threads Um para um • Cada thread no nível do usuário é mapeada para uma thread no nível do kernel • Exemplos – Windows NT/XP/2000 – Linux – Solaris 9 and later Muitos para muitos • Permite controlar o mapeamento de threads do usuário para threads no nível kernel – Evitar o número excessivo de threads no sistema – Economizar recursos • Exemplos – Solaris prior to version 9 – Windows NT/2000 with the ThreadFiber package Threads em Java • Gerenciada pela JVM – Mapeamento para o sistema operacional depende da implementação da JVM – Java Threads • Classe Thread ou • Interface Runnable Java Threads class TestThread implements Runnable { private String myname; public TestThread(String str){ myname= str; } public void run(){ System.out.println(myname); } } class Factory { public static void main(String[] args) { Thread t1; Thread t2; t1= new Thread(new TestThread("thread 1")); t2= new Thread(new TestThread("thread 2")); t1.start(); t2.start(); try{ t1.join(); t2.join(); }catch (InterruptedException e){ System.out.println(e); } } } Threads: Questões de projeto • • • • • Finalização de Threads Tratamento de sinais Thread pools Dados específicos Escalonamento Finalização de Thread • Finalizar uma thread antes de terminar sua execução • Duas formas de implementação: – Asynchronous cancellation: finaliza a thread imediatamente – Deferred cancellation: permite que a thread alvo verifique periodicamente se ela deve ser cancelada Java • Deferred cancellation Manipulação de sinais • Sinais: método geral de sinalização de processo no ambiente UNIX • Um signal handler recebe e trata o sinal • Possíveis implementações: – – – – Entregar o sinal para uma thread Entregar o sinal para todas as threads Entregar o sinal para algumas threads Atribuir um thread específica para receber os sinais Pthreads • A POSIX standard (IEEE 1003.1c) API para criar e manipular threads • API especifica o comportamento da biblioteca • Normalmente suportada em sistemas operacionais UNIX-like(Solaris, Linux, Mac OS X) Exemplo Pthreads #include <pthread.h> #include <stdlib.h> #include <unistd.h> void *thread_function(void *arg) { int i; for ( i=0; i<20; i++ ) { printf("Thread says hi!\n"); sleep(1); } return NULL; } int main(void) { pthread_t mythread; if ( pthread_create( &mythread, NULL, thread_function, NULL) ) { printf("error creating thread."); abort(); } if ( pthread_join ( mythread, NULL ) ) { printf("error joining thread."); abort(); } exit(0); } WindowsXP Threads • Implementa o mapeamento one-to-one • Cada thread contém – – – – Identificador Registradorres Pilha separadas para o nível user e kernel Área para armazenamento de dados privados Linux Threads • Linux utiliza os termos tasks e threads • clone() system call: cria uma thread • clone(): define quais serão os espaços de endereçamento que serão compartilhados Sincronização entre Threads • Pode ser implementado utilizando mutex, semafóros, monitores, etc. Java • Monitores – Funções ou métodos protegidos – Synchronized: apenas uma thread pode executar o método Exemplo public class Box { private Object boxContents; public synchronized Object get() { Object contents = boxContents; boxContents = null; return contents; } public synchronized boolean put(Object contents) { if (boxContents != null) return false; boxContents = contents; return true; } } Wait() e notify() • • • public class Semaphore { private int value; • • • public Semaphore(int value) { this.value = value; } • • • • • • • public synchronized void acquire() { while (value <= 0) { try { wait(); } catch (InterruptedException e) { } } • • } • • public synchronized void release() { ++value; • • • value--; notify(); } } Buffer de tamanho limitado • N posições, cada posição armazena um elemento • Semáforo mutex inicializado com 1 • Semáforo full inicializado com 0 • Semáforo empty inicializado com N. Produtor while (true) { // produce an item wait (empty); wait (mutex); // add the item to the buffer signal (mutex); signal (full); } Consumidor while (true) { wait (full); wait (mutex); // remove an item from buffer signal (mutex); signal (empty); // consume the removed item }