# Piattaforme e Software per la rete - lezione 3 #### William Fornaciari ###### 23 March 2016 ## Cosa sono i thread I thread sono nati per alleggerire il parallelismo su macchine lente Non sempre i thread sono vantaggiosi, se usati troppo sono svantaggiosi rispetto ai processi tradizionali. Un processo contiene - Risorse - Contesto di esecuzione I thread dello stesso processo condividono tutte le risorse aperte, con le dovute problematiche di concorrenza e sincronizzazione. Per questo sono stati introdotti i meccanismi di mutex tipici dei processi, anche per i thread. L'esempio classico sono i server, in cui posso creare tanti thread e all'occorrenza risvegliarli, inoltre su sistemi multicore posso dividere i thread sui vari core, per gestire il carico. ### Vantaggi L'overhead di creazione/distruzione di thread era di un fattore 10 rispetto ai processi nei primi sistemi linux che lo implementavano. Capostipite dei thread sono i solaris thread, che venivano usati da Solaris (girava su SPARC) Su windows sono venuti sfruttati bene da windows NT. I threads vennero introdotti da una libreria thread scritta da uno studente di Berkley e consistevano in una esecuzione di diverse funzioni in modo trasparente al kernel. Quindi i thread possono essere sia *kernel* che *utente* ### Team model Utile per partizionare un applicazione Si utilizza un thread diverso per ogni funzione, ad esempio si dedica un thread alla sola interazione utente, in modo da avere una maggiore reattività agli input. La prima applicazione dei thread è stata un foglio elettronico, in cui abbiamo un thread per input, uno per video e uno per il calcolo. Non è detto che un problema si riesca a mappare bene su un'architettura multicore, ad esempio perchè la complessità dei thread è sbilanciata, es: thread input o display sono molto più leggeri del thread computing. __Vantaggio principale__ è dare reattività all'esperienza utente. ### Architettura a dispatcher Un thread detto *dispatcher* riceve richieste di servizio e le invia ai vari thread. Si mappa molto bene su architetture a cluster, in cui abbiamo un core principale(dispatcher) e dei worker core con memoria condivisa a cui viene inviato il lavoro. Questa architettura presenta dei vantaggi per il risparmio energetico perchè posso tenere spenti i worker core finchè non arriva del lavoro da assegnargli. ### Architettura a pipeline Costituito da elementi con ingresso e uscita (es: bash pipe) In questo caso il secondo elemento ha un buffer di dati in ingresso e può elaborare senza dover scrivere/leggere da memoria. Vantaggiosa per effettuare delle ricerche, in quanto non serve elaborare tutti i dati per trovare un risultato. ### User thread package Viene implementato uno strato di supporto runtime a livello utente per gestire i thread Il supporto si occupa dello scheduling dei thread attivi di un processo. Simile a co-routine nella programmazione. __Difficile__ sfruttare i sistemi multicore __Facile__ da implementare ### Kernel thread package Se un thread è bloccato non blocca l'intero processo come nel caso utente. Serve implementare delle specifiche chiamate di sistema e modificare il kernel. ### Relazione tra thread e processi - Many-to-one: un solo processo gestisce tutti i thread - One-to-one: user-level thread viene mappato su kernel thread ### Comunicazione e sincronizzazione Le principali soluzioni per far comunicare i thread sono: - __Semafori:__ Contatore che viene incrementato e decrementato, i processi possono essere eseguiti quando è non negativo - __Mutex:__ Versione binaria del semaforo - __Condition Variable:__ - __Monitor e scambio messaggi__ ## Parallelismo * __Processo__ realizza il concetto di macchina virutale e ha un forte *isolamento* * __Thread__ utile per processi leggeri, in caso di errore può far fallire gli altri thread dello stesso processo o il processo stesso. I thread inoltre sono molto efficienti nel parallelismo e concorrenza rispetto ai processi. __Concorrenza__ nel caso di parallelismo reale può portare ad eseguire insieme i due processi In un sistema monoprocessore i due processi verranno eseguiti sequenzialmente ma non si sa in quale ordine __POSIX__ è un modo per standardizzare le interfacce dei sistemi operativi, per migliorare la *portabilità* del codice. ### Scheduling for uniprocessor systems __RIPASSARE__ Il carico dei processi di solito avviene a *burst*, seguiti dall'attesa per l'I/O Lo scheduler *preemptive* è più difficile da gestire rispetto ad uno normale