SlideShare ist ein Scribd-Unternehmen logo
1 von 66
Downloaden Sie, um offline zu lesen
Svantaggi legati all'uso di processi
• La gestione tradizionale dei processi può
  diventare molto onerosa dal punto di vista
  computazionale
  – Creazione: allocazione dello spazio di
    indirizzamento, e successiva popolazione
  – Context switch: salvataggio e ripristino degli
    spazi di indirizzamento (codice, dati, stack) di
    due processi
• Con una applicazione con molti processi
  (server), il SO rischia di passare la maggior
  parte del tempo a svolgere operazioni interne
  di gestione, piuttosto che ad eseguire codice
  applicativo
                                                       1
Svantaggi legati all'uso di processi
• La nozione classica di processo ingloba due
  concetti ben distinti, gestiti dal SO:
  – Gestione delle risorse: ciascun processo ha
    assegnati un proprio spazio di indirizzamento
    (solitamente, indipendente) ed alcune risorse
  – Esecuzione traccia: ciascun processo esegue
    porzioni di codice sequenzialmente e
    concorrentemente con altri processi
• La gestione dell'esecuzione di una traccia non
  comporta particolari aggravi computazionali,
  essendo direttamente gestita dal processore
• La lentezza della gestione risiede nella
  complessità della gestione delle risorse del
  processo                                          2
Separazione risorse-esecuzione
• Nei SO moderni, i due concetti ora visti
  possono essere disaccoppiati
  – L'unità base di esecuzione di una traccia prende
    il nome di thread
  – L'unità base proprietaria delle risorse prende il
    nome di processo
• Ciascun processo può essere visto come:
  – un contenitore di risorse
  – un contenitore di codice
  – Uno strumento per far partire tracce sequenziali
    (“fili” di codice, thread) di esecuzione del
    codice

                                                        3
Thread
• Un thread è l'insieme dei dati utilizzati per
  eseguire, in maniera concorrente, più tracce
  relative al codice di un processo
• Tutti i thread generati da un processo ne
  condividono il codice e le risorse
• In tal modo, le operazioni di gestione non
  toccano praticamente più lo spazio di
  indirizzamento!
  – L'aggravio di gestione si riduce sensibilmente
• Un SO in grado di gestire i thread è detto
  multithreaded
• Tutti i SO moderni supportano il multithreading
                                                     4
Ambiente a processi (single threaded)
• Ciascun processo      processo
                                               file
  contiene tutte le
                          PCB
  informazioni per
                                              dati
  poterlo eseguire
• Ambiente single                             stack
                           IP
  threaded: ciascun
  processo può
                           codice
  eseguire al più una
  traccia
                                 traccia in
• Informazioni:                 esecuzione
  – Spazio indirizzi
  – Risorse prenotate
  – Registri interni
                                                      5
Ambiente multithreaded
• Ciascun processo        processo
                                                    file
  contiene tutte le
                             PCB
  informazioni per
                                                   dati
  poterlo eseguire
• Ambiente                                        codice
                               IP
  multithreaded: ogni
  thread esegue
                            TCB         TCB        TCB
  tracce di codice
• TCB: Thread Control
                            IP stack   IP stack   IP stack
  Block (simile a PCB)
  – Registri, Stack       traccia in traccia in traccia in
                         esecuzione esecuzione esecuzione
  – Variabili “locali”
  – Stato esecuzione
                                                             6
Processi vs. Thread




Processo           Thread


                            7
Benefici del multithreading
• Reattività
  – Il blocco di un thread non inficia gli altri
  – Maggiore fluidità di esecuzione
• Condivisione risorse
  – I thread condividono la memoria e le risorse del
    processo che li ha generati
• Economia
  – Alloco e distruggo risorse di processo una volta
• Architetture SMP
  – I thread eseguono in parallelo sui diversi
    processori
  – Il singolo processo non li può sfruttare
                                                       8
Problemi del multithreading
• Modello di programmazione complesso
  – La condivisione delle risorse e della memoria
    implica spesso la gestione della concorrenza
    degli accessi a queste ultime
  – Ulteriori passi di programmazione, spesso
    complessi
• Debugging complesso
  – E' molto difficile riprodurre bug in presenza di
    accessi concorrenti alle risorse
  – E' spesso difficile individuare le cause del bug




                                                       9
Applicazioni del multithreading
• Quali applicazioni si lasciano implementare
  tramite i thread? Tutte quelle applicazioni:
  – che possono essere spezzate in più parti da
    eseguire concorrentemente/parallelamente
  – in cui alcune parti si bloccano spesso per fare I/
    O, mentre altre no
  – che devono gestire eventi asincroni (bottone
    STOP del browser)




                                                         10
Supporto del SO ai thread
• Il SO deve fornire un supporto per la gestione
  dei thread
  – Supporto allo user level, tramite librerie di
    funzioni (API) per gestire n thread in esecuzione
  – Supporto al kernel level, tramite una astrazione
    di traccia di esecuzione
• Le diverse implementazioni di supporto ai
  thread svariano da un estremo all'altro
  – Implementazioni puramente a livello applicativo
  – Implementazioni puramente a livello kernel
  – Implementazioni “miste”
• Adozione di molteplici modelli di
  multithreading
                                                        11
Modello Many-to-One (N:1)
• A più supporti user level corrisponde un solo
  supporto kernel level
   – Il kernel vede una sola traccia di esecuzione,
     ossia solo un processo che esegue
   – Il processo usa delle funzionalità applicative per
     simulare uno scheduler di mini-processi
   – I mini-processi non sono noti al kernel del SO
   – Ciascun mini-processo è, in realtà, una
     astrazione per eseguire una traccia di una
     funzione del processo
• Implementazioni: Green threads (Solaris), GNU
  Portable Threads, Java threads, Ruby threads

                                                          12
Modello Many-to-One (N:1)
                        Create, stop, schedule,
Processo
                           resume, destroy
             Main
                                        Thread
                                        library    User
                                                  space
    Thread     Thread         Thread




             PCB
                                                  Kernel
                                                  space




                                                           13
Modello Many-to-One (N:1)
• Vantaggi
  – Gestione efficientissima dei thread (non viene
    coinvolto lo scheduler del kernel)
  – Non richiede un kernel multithreaded per poter
    essere implementato
• Svantaggi
  – Se un thread effettua una chiamata bloccante, il
    processo si blocca, e con esso tutti i thread
  – I thread sono legati allo stesso processo, e non
    possono eseguire su processori fisici distinti



                                                       14
Modello One-to-One (1:1)
• Ad un supporto user level corrisponde un
  supporto kernel level
  – Il kernel vede una traccia di esecuzione distinta
    per thread; ho l'analogo di un PCB per ciascun
    thread in esecuzione
  – Il processo usa una system call simile a fork()
    per invocare il meccanismo di creazione
  – I thread vengono schedulati dallo scheduler del
    kernel, come tutti gli altri processi
• Implementazioni: GNU/Linux (LinuxThreads,
  NPTL), Windows 95/98/2000/XP/NT


                                                        15
Modello One-to-One (1:1)
Processo        Thread       Thread

                   Thread       Thread
     Main
                  function     function    User
                                          space
Create,
            f
destroy




                                          Kernel
    PCB           TCB          TCB
                                          space




                                                   16
Modello One-to-One (1:1)
• Vantaggi
  – Se un thread effettua una chiamata bloccante,
    non blocca gli altri thread
  – I thread sono rappresentati da altrettanti TCB, e
    possono essere eseguiti su processori fisici
    distinti
• Svantaggi
  – Gestione meno efficiente dei thread (usa lo
    scheduler del kernel)
  – Richiede un kernel multithreaded per poter
    essere implementato


                                                        17
Modello Many-to-Many (N:M)
• Ad N supporti user level corrispondono M
  supporti kernel level (N>M)
  – Unione del modelli 1:1 ed N:1; intende prendere
    il meglio dei due modelli
  – Il processo usa una system call simile a fork()
    per creare M thread kernel level
  – Ciascuno di questi M kernel level thread crea N/
    M thread user level
• Implementazioni: IRIX, HP-UX, Tru64 UNIX,
  Solaris (fino a V.9)



                                                       18
Modello Many-to-Many (N:M)
     ProcessoCreate, stop, sched,   ProcessoCreate, stop, sched,
              resume, destroy                resume, destroy
        Main                           Main
                          Thread                         Thread
                          library                        library
                                                                    User
                                                                   space
      Thread Thread Thread           Thread Thread Thread




                                                                   Kernel
            PCB                               TCB
                                                                   space
Create,
destroy




                                                                            19
Quando si applicano i modelli?
• Modello Many-to-One
  – Buono per applicazioni di tipo parallelo con
    pochissimo I/O
  – Lo scheduler del kernel non le rallenta
  – Thread non schedulabili su più processori
• Modello One-to-One
  – Ideale per applicazioni di tipo parallelo o
    distribuito con tanto I/O (server)
  – Mantiene elevato il grado di concorrenza
  – Ha soppiantato tutti gli altri modelli
• Modello Many-to-Many
  – Concepito per applicazioni suddivise in una
    parte I/O (1:1) ed in una parte di calcolo (M:1)   20
Multithreading: creazione/immagine
• In un programma multithreaded la semantica
  delle operazioni fork() ed exec() cambia
• Se un thread invoca la chiamata fork():
  – può duplicare se stesso
  – può duplicare l'intero gruppo di thread
• Se un thread invoca la chiamata exec():
  – Sovrascrive l'immagine di tutti i thread e del
    processo invocante
• Solitamente, si evita l'uso della exec() in
  ambiente multithreaded
  – Si associano i thread a funzioni che devono
    essere eseguite

                                                     21
Multithreading: cancellazione
• La cancellazione è l'operazione di terminazione
  prematura di un thread
• Il thread selezionato per una cancellazione è
  chiamato thread bersaglio (target thread)
• La cancellazione del target bersaglio può
  avvenire in due modalità distinte:
  – cancellazione asincrona: un altro thread uccide
    direttamente il thread bersaglio
  – cancellazione differita: il thread bersaglio
    controlla periodicamente (cancellation point) se
    deve terminare, in modo da uscire in maniera
    pulita

                                                       22
Multithreading: gestione segnali
• In ambiente single threaded, il segnale viene
  inviato ad un processo
• In ambiente multithreaded, a quale thread va
  inviato il segnale?
  – al thread cui il segnale si riferisce
  – a ciascun thread (CTRL-C)
  – a specifici thread
     ♦ il primo thread che non blocca il segnale
     ♦ Identificato dal TID
  – ad un thread speciale, di controllo (Solaris 2)



                                                      23
Multithreading: thread pool
• All'aumentare del numero di flussi concorrenti,
  le risorse del sistema possono esaurire
  rapidamente
• Per impedire l'esaurimento delle risorse, un
  software multithreaded pre-crea un insieme di
  thread (thread pool)
  – Quando viene lanciato un thread, lo si preleva
    dal gruppo
  – Quando un thread termina, lo si restituisce al
    gruppo
  – Le operazioni di creazione/distruzione sono
    molto più veloci
  – Si limita il numero di thread in esecuzione
                                                     24
Multithreading: Thread Specific Data
• In particolari circostanze, ciascun thread può
  necessitare di una copia privata di alcuni dati,
  detti dati specifici (thread locale)
  – Variabili “globali” per thread
  – Variabili “static” per thread
• La maggior parte delle librerie pthread
  forniscono il supporto per i thread locale




                                                     25
Modelli di programmazione
• L'uso dei thread permette l'implementazione
  efficiente di alcuni modelli di programmazione
• Modello Pipeline:
  – I thread eseguono “a catena”, uno dopo l'altro
• Modello Master-Slave:
  – Il thread master coordina l'esecuzione dei
    thread slave (che effettuano il lavoro vero e
    proprio)
• Modello Worker:
  – Tutti i thread lavorano



                                                     26
Modelli di programmazione


Pipeline

                      M

Master-Slave
                  S   S       S



                  W
                          W
Worker
                  W
                          W
                                  27
Librerie di threading
• Ciascuna implementazione del supporto ai
  thread fornisce una libreria di funzioni (thread
  library) per la gestione dei thread
  – La libreria può fare uso nullo, parziale o
    completo delle funzionalità offerte dal kernel
• Implementazioni:
  – Pthreads: standard POSIX, kernel level
  – Win32: kernel level
  – Java: user level




                                                     28
Libreria Pthreads
• Standard ANSI/IEEE POSIX 1003.1
  – Gestione thread: creazione, distruzione,
    sincronizzazione
  – Gestione concorrenza: meccanismo dei mutex
  – Comunicazione concorrente: meccanismo per
    creare, distruggere e segnalare thread sulla
    base dei valori di specifiche variabili condizione
    (condition variables)
• Più di 60 funzioni per gestire thread come tipi
  di dato opachi (pthread_t)
• Concepita per i linguaggi C, C++
• Compilazione: gcc -pthread
  – include <pthread.h>
                                                         29
Creazione thread
• Signature: int pthread_create(
  pthread_t *thread, pthread_attr_t *attr,
  void *(*start_routine)(void *), void *arg);
  – Descrizione: crea un nuovo thread, eseguente
    la funzione start_routine con argomento arg
  – Ingresso:
     ♦ Un puntatore alla struttura thread identificante il
       thread da eseguire
     ♦ Un puntatore alla struttura “attributi” che
       imposta le caratteristiche del thread (NULL)
     ♦ Un puntatore alla funzione start_routine
     ♦ Un puntatore all'argomento arg



                                                             30
Creazione thread
• Signature: int pthread_create(
  pthread_t *thread, pthread_attr_t *attr,
  void *(*start_routine)(void *), void *arg);
  – Descrizione: crea un nuovo thread, eseguente
    la funzione start_routine con argomento arg
  – Ritorno:
     ♦ 0 -> tutto ok
         – Il TID del thread appena creato è salvato
           all'interno della struttura dati thread
     ♦ !=0 -> errore
         – tipicamente, le risorse del sistema sono
           insufficienti per la creazione di un thread

                                                         31
Creazione thread
• Un thread, a sua volta, può creare altri thread con
  la pthread_create()
• Non esiste gerarchia o dipendenza fra I vari
  thread




                                                        32
Terminazione thread
• Le cause di terminazione di un thread sono
  molteplici
  – Il thread ritorna dalla funzione
  – Il thread invoca una chiamata di funzione
    pthread_exit()
  – Il thread è cancellato da un altro thread tramite
    la funzione pthread_cancel()
  – Il processo invocante carica un'altra immagine
    con la funzione exec()
  – Il processo invocante esce tramite la funziona
    exit()


                                                        33
Terminazione thread
• Signature: void pthread_exit(void *retval);
  – Descrizione: termina l'esecuzione del thread
    invocante
  – Ingresso:
     ♦ un puntatore ad una variabile in cui sarà
       scritto il codice di uscita del thread (potrà
       essere consultato tramite la pthread_join())
  – Ritorno: nessuno




                                                       34
Attributi dei thread
• Ad un thread è associata una struttura dati
  identificante le sue proprietà (attributi):
  pthread_attr_t
• Tale struttura contiene una maschera di bit,
  che rappresenta le proprietà attivate
• Alcune proprietà:
  – Thread “joinabile”
  – Algoritmo di scheduling utilizzato
  – Scope delle variabili




                                                 35
Attributi dei thread
• Signature: int pthread_attr_init(pthread_attr_t
  *attr);
  – Descrizione: inizializza una struttura
    pthread_attr_t
  – Ingresso:
     ♦ un puntatore ad una struttura pthread_attr_t
  – Ritorno:
     ♦ Sempre 0




                                                      36
Attributi dei thread
• Signature: int pthread_attr_destroy
  (pthread_attr_t *attr);
  – Descrizione: resetta una struttura pthread_attr_t
    e rilascia le risorse allocate
  – Ingresso:
     ♦ un puntatore ad una struttura pthread_attr_t
  – Ritorno:
     ♦ Sempre 0




                                                        37
Attributi dei thread
• Signature: int pthread_set_detachstate
  (pthread_attr_t *attr, int detachstate);
  – Descrizione: imposta il flag “detached” del
    thread con proprietà attr al valore detachstate
  – Ingresso:
     ♦ Un puntatore ad una struttura pthread_attr_t
     ♦ Lo stato desiderato
       (PTHREAD_CREATE_JOINABLE)
  – Ritorno:
     ♦ 0: -> tutto OK
     ♦ !=0: un errore



                                                      38
Attributi dei thread
• Signature: int pthread_set_detachstate
  (pthread_attr_t *attr, int detachstate);
  – Descrizione: imposta il flag “detached” del
    thread con proprietà attr al valore detachstate
  – Ingresso:
     ♦ Un puntatore ad una struttura pthread_attr_t
     ♦ Lo stato desiderato
       (PTHREAD_CREATE_JOINABLE)
  – Ritorno:
     ♦ 0: -> tutto OK
     ♦ !=0: un errore



                                                      39
Sincronizzazione thread
• La sincronizzazione fra thread creante e thread
  avviene in maniera simile ai processi
• Si utilizza la funzione pthread_join() (analogo
  della waitpid())
• Il thread invocante (o il processo) si blocca
  fino a quando un thread specificato da
  threadid termina
• Il thread invocante (o il processo) può leggere
  il codice di uscita
• A differenza dei processi, bisogna specificare
  esplicitamente che un thread sia “joinabile”


                                                    40
Sincronizzazione thread
• Come si specifica la proprietà “joinable” sui
  thread?
• Step 1: si dichiara una variabile “attributi” di
  tipo pthread_attr_t
• Step 2: si inizializza la variabile con la funzione
  pthread_attr_init()
• Step 3: si imposta l'attributo “detached” con la
  funzione pthread_attr_setdetachstate()
• Step 4: in un punto successivo, si rilasciano le
  risorse allocate con la funzione
  pthread_attr_destroy()


                                                        41
Sincronizzazione thread




                          42
Sincronizzazione thread
• Signature: int pthread_join (pthread_t th, void
  **thread_return);
  – Descrizione:
     ♦ sospende l'esecuzione del thread invocante
       fino all'uscita del thread identificato da th
     ♦ Se thread_return != NULL, scrive il codice di
       uscita nella cella puntata da thread_return
  – Ingresso:
     ♦ un puntatore ad una struttura pthread_attr_t
  – Ritorno:
     ♦ 0: -> tutto OK
     ♦ !=0: un errore

                                                       43
Concorrenza thread
• Per gestire l'accesso concorrente a variabili
  condivise, si utilizza il costrutto dei semafori
  – Variabili mutex (MUTual Exclusion): interi posti
    a 0 (risorsa libera) o 1 (risorsa occupata)
    pthread_mutex_t
  – Ciascun mutex agisce come un lucchetto (lock)
    sugli altri thread che vogliono accedere alla
    risorsa
  – Due stati:
     ♦ LOCKED: risorsa prenotata da un thread
     ♦ UNLOCKED: risorsa libera
  – Impedisce le cosiddette corse critiche (accessi
    simultanei a variabili condivise, con
    indeterminatezza del risultato finale)             44
Concorrenza thread
• Scenario tipico di utilizzo dei mutex
  – Creazione ed inizializzazione di una variabile di
    tipo mutex
  – Più thread provano a prenotare la risorsa,
    cercando di ottenere il lock sul mutex
  – Un solo thread ci riesce (quello che arriva per
    primo) e prenota la risorsa per se
  – Il thread modifica la risorsa in questione
  – Il thread rilascia la risorsa
  – Un altro thread acquisisce il lock sul mutex
  – Il processo si ripete
  – Il mutex viene distrutto

                                                        45
Concorrenza thread
• Dichiarazione mutex: può avvenire in due modi
  distinti
  – Dichiarazione statica:
    pthread_mutex_t mymutex =
    PTHREAD_MUTEX_INITIALIZER;
  – Dichiarazione dinamica:
    pthread_mutex_init()




                                                  46
Concorrenza thread
• Signature: int pthread_mutex_init
  (pthread_mutex_t *mutex, const
  pthread_mutex_attr_t *mutexattr);
  – Descrizione:
     ♦ Inizializza il mutex puntato da mutex con gli
       attributi puntati di mutexattr
     ♦ Il mutex è UNLOCKED (risorsa libera)
  – Ingresso:
     ♦ un puntatore ad una struttura
       pthread_mutex_t
     ♦ un puntatore ad una struttura
       pthread_mutex_attr_t
  – Ritorno:
     ♦ Sempre 0                                        47
Concorrenza thread
• Signature: int pthread_mutex_destroy
  (pthread_mutex_t *mutex);
  – Descrizione:
     ♦ Resetta lo stato del mutex puntato da mutex
  – Ingresso:
     ♦ un puntatore ad una struttura
       pthread_mutex_t
  – Ritorno:
     ♦ 0: -> tutto OK
     ♦ !=0: il mutex è attualmente bloccato




                                                     48
Concorrenza thread
• Signature: int pthread_mutex_lock
  (pthread_mutex_t *mutex);
  – Descrizione:
     ♦ Prova ad acquisire un lock su mutex
     ♦ Se mutex=UNLOCKED, lo acquisisce e torna
     ♦ Se mutex=LOCKED, si blocca fino a quando la
       risorsa non si libera
  – Ingresso:
     ♦ un   puntatore ad una struttura pthread_mutex_t
  – Ritorno:
     ♦ 0: -> tutto OK
     ♦ !=0: mutex non inizializzato o già bloccato dallo
       stesso thread
                                                           49
Concorrenza thread
• Signature: int pthread_mutex_trylock
  (pthread_mutex_t *mutex);
  – Descrizione:
     ♦ Provaad acquisire un lock su mutex
     ♦ Se mutex=UNLOCKED, lo acquisisce e torna
     ♦ Se mutex=LOCKED, ritorna e non si blocca

  – Ingresso:
     ♦ un   puntatore ad una struttura pthread_mutex_t
  – Ritorno:
     ♦ 0: -> tutto OK
     ♦ !=0: mutex non inizializzato, già bloccato dallo
       stesso thread, già bloccato da un altro thread

                                                          50
Concorrenza thread
• Signature: int pthread_mutex_unlock
  (pthread_mutex_t *mutex);
  – Descrizione:
     ♦ Rilascia
              la risorsa associata al mutex
     ♦ Reimposta il mutex ad UNLOCKED

  – Ingresso:
     ♦ un   puntatore ad una struttura pthread_mutex_t
  – Ritorno:
     ♦ 0: -> tutto OK
     ♦ !=0: mutex non inizializzato, già bloccato dallo
       stesso thread, già bloccato da un altro thread



                                                          51
Variabili condizione
• Le variabili condizione costituiscono un
  ulteriore meccanismo per la sincronizzazione
  fra thread
• Idea: associare eventi al valore di alcune
  variabili
   – Una variabile assume un valore->scatta un
     evento
   – Un'altra variabile, detta variabile condizione,
     viene usata per segnalare l'evento
   – Callback: gestione asincrona di eventi tramite
     invocazione di funzioni
• Senza le variabili di condizione, un thread deve
  continuamente controllare (poll) l'arrivo di eventi,
  sprecando inutilmente risorse di calcolo               52
Variabili condizione
• Scenario tipico di utilizzo - variabili condizione
• Tre thread:
  – Thread Main: thread di controllo che schedula i
    thread di lavoro A e B
  – Thread A: lavora fino ad un certo punto, poi si
    ferma in attesa di un evento
  – Thread B: lavora fino ad un certo punto, poi
    scatena l'evento sul quale sta aspettando A
• Che funzioni eseguono i tre thread?




                                                       53
Variabili condizione
• Thread Main:
  – Dichiara ed inizializza (strutture) dati globali che
    necessitano di sincronizzazione
  – Dichiara ed inizializza un oggetto di tipo
    “variabile condizione”
  – Dichiara ed inizializza un mutex associato alla
    variabile condizione
  – Crea i thread A e B
  – Join dei thread A e B




                                                           54
Variabili condizione
• Thread A:
  – Lavora fino a quando non si deve interrompere,
    in attesa che una condizione si verifichi
  – Acquisisce il lock sul mutex
  – Si blocca (pthread_cond_wait()) fino a quando
    non si verifica l'evento, segnalato da un altro
    thread (Thread B)
  – pthread_cond_wait() sblocca automaticamente
    il mutex, che può essere utilizzato dall'altro
    thread per acquisire uso esclusivo sulla
    variabile che rappresenta l'evento
  – Quando arriva il segnale, Thread A si sveglia ed
    il mutex viene di nuovo assegnato a lui
  – Thread A rilascia esplicitamente il mutex          55
Variabili condizione
• Thread B:
  – Lavora
  – Acquisisce il lock sul mutex
  – Cambia il valore della variabile su cui è bloccato
    Thread A
  – Se il valore della variabile è tale da scatenare un
    evento, segnala Thread A tramite una variabile
    condizione
  – Rilascia esplicitamente il mutex




                                                          56
Variabili condizione
• Rappresentate dal tipo di dato opaco
  pthread_cond_t
• Devono essere inizializzate prima di poter
  essere utilizzate
• Possono specificare dei propri attributi
• L'inizializzazione avviene in due modi distinti:
  – Inizializzazione statica:
    pthread_cond_t myconvar =
    PTHREAD_COND_INITIALIZER;
  – Inizializzazione dinamica:
    pthread_cond_init()


                                                     57
Variabili condizione
• Signature: int pthread_cond_init
  (pthread_cond_t *cond, const
  pthread_condattr_t *cond_attr);
  – Descrizione:
     ♦ Inizializza la variabile condizione cond
       utilizzando gli attributi cond_attr (NULL per
       default)
  – Ingresso:
     ♦ un puntatore ad una struttura
       pthread_cond_t
     ♦ un puntatore ad una struttura
       pthread_condattr_t
  – Ritorno:
     ♦ Sempre 0                                        58
Variabili condizione
• Signature: int pthread_cond_destroy
  (pthread_cond_t *cond);
  – Descrizione:
     ♦ Resetta una variabile condizione cond,
       rilasciando le risorse che potrebbe avere
       allocato
  – Ingresso:
     ♦ un puntatore ad una struttura
       pthread_cond_t
  – Ritorno:
     ♦ 0: -> tutto OK
     ♦ !=0: la variabile condizione è attualmente
       utilizzata da un qualche thread
                                                    59
Variabili condizione
• Signature: int pthread_condattr_init
  (pthread_condattr_t *attr);
  – Descrizione: inizializza una struttura
    pthread_condattr_t
  – Ingresso:
     ♦ un puntatore ad una struttura
       pthread_condattr_t
  – Ritorno:
     ♦ Sempre 0




                                             60
Variabili condizione
• Signature: int pthread_condattr_init
  (pthread_condattr_t *attr);
  – Descrizione: inizializza una struttura
    pthread_condattr_t
  – Ingresso:
     ♦ un puntatore ad una struttura
       pthread_condattr_t
  – Ritorno:
     ♦ Sempre 0




                                             61
Variabili condizione
• Signature: int pthread_condattr_destroy
  (pthread_condattr_t *attr);
  – Descrizione: resetta una struttura
    pthread_condattr_t
  – Ingresso:
     ♦ un puntatore ad una struttura
       pthread_condattr_t
  – Ritorno:
     ♦ Sempre 0




                                            62
Variabili condizione
• Signature: int pthread_cond_wait
  (pthread_cond_t *cond, pthread_mutex_t
  *mutex);
  – Descrizione:
     ♦ Blocca il thread invocante fino a quando non
       viene segnalata la condizione cond
     ♦ Deve essere invocata con mutex bloccato
       (altrimenti un thread potrebbe segnalare la
       condizione prima che un altro possa
       ascoltarla); il mutex viene automaticamente
       sbloccato al termine della chiamata
     ♦ Quando si verifica la condizione, il thread
       viene svegliato e mutex viene acquisito di
       nuovo (ricordatevi di rilasciarlo!)
                                                      63
Variabili condizione
• Signature: int pthread_cond_wait
  (pthread_cond_t *cond, pthread_mutex_t
  *mutex);
  – Ingresso:
     ♦ Un puntatore alla struttura pthread_cont_t
       che rappresenta la variabile condizione su
       cui aspettare
     ♦ Un puntatore alla struttura pthread_mutex_t
       che rappresenta il mutex associato alla
       variabile condizione
  – Ritorno:
     ♦ Sempre 0


                                                     64
Variabili condizione
• Signature: int pthread_cond_signal
  (pthread_cond_t *cond);
  – Descrizione:
     ♦ Segnala (risveglia) un altro thread in seguito
       al verificarsi di una data condizione
     ♦ Più thread possono aspettare una data
       condizione; pthread_cond_signal() ne
       risveglia solamente uno
  – Ingresso:
     ♦ Un puntatore alla struttura pthread_cont_t
       che rappresenta la variabile condizione su
       cui aspettare
  – Ritorno:
     ♦ Sempre 0                                         65
Variabili condizione
• Signature: int pthread_cond_broadcast
  (pthread_cond_t *cond);
  – Descrizione:
     ♦ Segnala (risveglia) un insieme di thread in
       seguito al verificarsi di una data condizione
     ♦ Più thread possono aspettare una data
       condizione; pthread_cond_broadcast() li
       risveglia tutti
  – Ingresso:
     ♦ Un puntatore alla struttura pthread_cont_t
       che rappresenta la variabile condizione su
       cui aspettare
  – Ritorno:
     ♦ Sempre 0                                        66

Weitere ähnliche Inhalte

Was ist angesagt?

Chapter 03 arithmetic for computers
Chapter 03   arithmetic for computersChapter 03   arithmetic for computers
Chapter 03 arithmetic for computersBảo Hoang
 
"Emerging Processor Architectures for Deep Learning: Options and Trade-offs,"...
"Emerging Processor Architectures for Deep Learning: Options and Trade-offs,"..."Emerging Processor Architectures for Deep Learning: Options and Trade-offs,"...
"Emerging Processor Architectures for Deep Learning: Options and Trade-offs,"...Edge AI and Vision Alliance
 
Programmable Logic Devices : SPLD and CPLD
Programmable Logic Devices : SPLD and CPLDProgrammable Logic Devices : SPLD and CPLD
Programmable Logic Devices : SPLD and CPLDUsha Mehta
 
Interrupt handling
Interrupt handlingInterrupt handling
Interrupt handlingmaverick2203
 
Chapter 2-8085 Microprocessor Architecture and Microcomputer Systems
Chapter 2-8085 Microprocessor Architecture and Microcomputer SystemsChapter 2-8085 Microprocessor Architecture and Microcomputer Systems
Chapter 2-8085 Microprocessor Architecture and Microcomputer Systemscmkandemir
 
Il protocollo informatico e gestione documentale
Il protocollo informatico e gestione documentaleIl protocollo informatico e gestione documentale
Il protocollo informatico e gestione documentaleCesare Ciabatti
 
Risc cisc Difference
Risc cisc DifferenceRisc cisc Difference
Risc cisc DifferenceSehrish Asif
 
Pipeline processing - Computer Architecture
Pipeline processing - Computer Architecture Pipeline processing - Computer Architecture
Pipeline processing - Computer Architecture S. Hasnain Raza
 
L9 understanding-atmega328 p-2
L9 understanding-atmega328 p-2L9 understanding-atmega328 p-2
L9 understanding-atmega328 p-2rsamurti
 
Module 4 advanced microprocessors
Module 4 advanced microprocessorsModule 4 advanced microprocessors
Module 4 advanced microprocessorsDeepak John
 
Presentation on flynn’s classification
Presentation on flynn’s classificationPresentation on flynn’s classification
Presentation on flynn’s classificationvani gupta
 
INSTRUCTION LEVEL PARALLALISM
INSTRUCTION LEVEL PARALLALISMINSTRUCTION LEVEL PARALLALISM
INSTRUCTION LEVEL PARALLALISMKamran Ashraf
 
Csc1401 lecture03 - computer arithmetic - arithmetic and logic unit (alu)
Csc1401   lecture03 - computer arithmetic - arithmetic and logic unit (alu)Csc1401   lecture03 - computer arithmetic - arithmetic and logic unit (alu)
Csc1401 lecture03 - computer arithmetic - arithmetic and logic unit (alu)IIUM
 
Coa module2
Coa module2Coa module2
Coa module2cs19club
 

Was ist angesagt? (20)

Ccna report
Ccna reportCcna report
Ccna report
 
Chapter 03 arithmetic for computers
Chapter 03   arithmetic for computersChapter 03   arithmetic for computers
Chapter 03 arithmetic for computers
 
"Emerging Processor Architectures for Deep Learning: Options and Trade-offs,"...
"Emerging Processor Architectures for Deep Learning: Options and Trade-offs,"..."Emerging Processor Architectures for Deep Learning: Options and Trade-offs,"...
"Emerging Processor Architectures for Deep Learning: Options and Trade-offs,"...
 
Programmable Logic Devices : SPLD and CPLD
Programmable Logic Devices : SPLD and CPLDProgrammable Logic Devices : SPLD and CPLD
Programmable Logic Devices : SPLD and CPLD
 
Interrupt handling
Interrupt handlingInterrupt handling
Interrupt handling
 
Chapter 2-8085 Microprocessor Architecture and Microcomputer Systems
Chapter 2-8085 Microprocessor Architecture and Microcomputer SystemsChapter 2-8085 Microprocessor Architecture and Microcomputer Systems
Chapter 2-8085 Microprocessor Architecture and Microcomputer Systems
 
Il protocollo informatico e gestione documentale
Il protocollo informatico e gestione documentaleIl protocollo informatico e gestione documentale
Il protocollo informatico e gestione documentale
 
Risc cisc Difference
Risc cisc DifferenceRisc cisc Difference
Risc cisc Difference
 
8086 Architecture
8086 Architecture8086 Architecture
8086 Architecture
 
Pipeline processing - Computer Architecture
Pipeline processing - Computer Architecture Pipeline processing - Computer Architecture
Pipeline processing - Computer Architecture
 
Mimd
MimdMimd
Mimd
 
Internal microprocessor architecture
Internal microprocessor architectureInternal microprocessor architecture
Internal microprocessor architecture
 
8086
80868086
8086
 
L9 understanding-atmega328 p-2
L9 understanding-atmega328 p-2L9 understanding-atmega328 p-2
L9 understanding-atmega328 p-2
 
Module 4 advanced microprocessors
Module 4 advanced microprocessorsModule 4 advanced microprocessors
Module 4 advanced microprocessors
 
Presentation on flynn’s classification
Presentation on flynn’s classificationPresentation on flynn’s classification
Presentation on flynn’s classification
 
INSTRUCTION LEVEL PARALLALISM
INSTRUCTION LEVEL PARALLALISMINSTRUCTION LEVEL PARALLALISM
INSTRUCTION LEVEL PARALLALISM
 
Csc1401 lecture03 - computer arithmetic - arithmetic and logic unit (alu)
Csc1401   lecture03 - computer arithmetic - arithmetic and logic unit (alu)Csc1401   lecture03 - computer arithmetic - arithmetic and logic unit (alu)
Csc1401 lecture03 - computer arithmetic - arithmetic and logic unit (alu)
 
Coa module2
Coa module2Coa module2
Coa module2
 
pipelining
pipeliningpipelining
pipelining
 

Ähnlich wie Sistemi Operativi: Thread - Lezione 08

Linux Kernel, driver e compilazione
Linux Kernel, driver e compilazioneLinux Kernel, driver e compilazione
Linux Kernel, driver e compilazioneFulvio Corno
 
Utilizzo dei Thread
Utilizzo dei ThreadUtilizzo dei Thread
Utilizzo dei ThreadLuca Vitale
 
Open Source Parallel Computing ltcsp
Open Source Parallel Computing ltcspOpen Source Parallel Computing ltcsp
Open Source Parallel Computing ltcspLaura Camellini
 
Introduzione User Mode Linux
Introduzione User Mode LinuxIntroduzione User Mode Linux
Introduzione User Mode LinuxMajong DevJfu
 
Moduli del kernel - Boot del sistema
 Moduli del kernel - Boot del sistema Moduli del kernel - Boot del sistema
Moduli del kernel - Boot del sistemaFulvio Corno
 
Introduzione Alla Uml Mconsole
Introduzione Alla Uml MconsoleIntroduzione Alla Uml Mconsole
Introduzione Alla Uml MconsoleMajong DevJfu
 
Software libero nei sistemi embedded
Software libero nei sistemi embeddedSoftware libero nei sistemi embedded
Software libero nei sistemi embeddedDaniele Costarella
 
Sistemi Operativi: Componenti - Lezione 02
Sistemi Operativi: Componenti - Lezione 02Sistemi Operativi: Componenti - Lezione 02
Sistemi Operativi: Componenti - Lezione 02Majong DevJfu
 
OpenCL - Introduzione al framework OpenCL
OpenCL - Introduzione al framework OpenCLOpenCL - Introduzione al framework OpenCL
OpenCL - Introduzione al framework OpenCLFrancesco Garofalo
 
Sistemi Operativi: Struttura - Lezione 04
Sistemi Operativi: Struttura - Lezione 04Sistemi Operativi: Struttura - Lezione 04
Sistemi Operativi: Struttura - Lezione 04Majong DevJfu
 
Summary of “The Case for Writing Network Drivers in High-Level Programming La...
Summary of “The Case for Writing Network Drivers in High-Level Programming La...Summary of “The Case for Writing Network Drivers in High-Level Programming La...
Summary of “The Case for Writing Network Drivers in High-Level Programming La...LeonardoIurada
 
Sistemi Operativi: Struttura avanzata - Lezione 05
Sistemi Operativi: Struttura avanzata - Lezione 05Sistemi Operativi: Struttura avanzata - Lezione 05
Sistemi Operativi: Struttura avanzata - Lezione 05Majong DevJfu
 

Ähnlich wie Sistemi Operativi: Thread - Lezione 08 (20)

Thread
ThreadThread
Thread
 
Linux Kernel, driver e compilazione
Linux Kernel, driver e compilazioneLinux Kernel, driver e compilazione
Linux Kernel, driver e compilazione
 
Utilizzo dei Thread
Utilizzo dei ThreadUtilizzo dei Thread
Utilizzo dei Thread
 
Open Source Parallel Computing ltcsp
Open Source Parallel Computing ltcspOpen Source Parallel Computing ltcsp
Open Source Parallel Computing ltcsp
 
Thread
ThreadThread
Thread
 
Introduzione User Mode Linux
Introduzione User Mode LinuxIntroduzione User Mode Linux
Introduzione User Mode Linux
 
Moduli del kernel - Boot del sistema
 Moduli del kernel - Boot del sistema Moduli del kernel - Boot del sistema
Moduli del kernel - Boot del sistema
 
Introduzione Alla Uml Mconsole
Introduzione Alla Uml MconsoleIntroduzione Alla Uml Mconsole
Introduzione Alla Uml Mconsole
 
Presentazione tesi 2.0
Presentazione tesi 2.0Presentazione tesi 2.0
Presentazione tesi 2.0
 
Software libero nei sistemi embedded
Software libero nei sistemi embeddedSoftware libero nei sistemi embedded
Software libero nei sistemi embedded
 
Da DotNet a DotNetCore
Da DotNet a DotNetCoreDa DotNet a DotNetCore
Da DotNet a DotNetCore
 
Sistemi Operativi: Componenti - Lezione 02
Sistemi Operativi: Componenti - Lezione 02Sistemi Operativi: Componenti - Lezione 02
Sistemi Operativi: Componenti - Lezione 02
 
OpenCL - Introduzione al framework OpenCL
OpenCL - Introduzione al framework OpenCLOpenCL - Introduzione al framework OpenCL
OpenCL - Introduzione al framework OpenCL
 
Sistemi Operativi: Struttura - Lezione 04
Sistemi Operativi: Struttura - Lezione 04Sistemi Operativi: Struttura - Lezione 04
Sistemi Operativi: Struttura - Lezione 04
 
Summary of “The Case for Writing Network Drivers in High-Level Programming La...
Summary of “The Case for Writing Network Drivers in High-Level Programming La...Summary of “The Case for Writing Network Drivers in High-Level Programming La...
Summary of “The Case for Writing Network Drivers in High-Level Programming La...
 
Cloud Computing
Cloud ComputingCloud Computing
Cloud Computing
 
Cell Programming 1
Cell Programming 1Cell Programming 1
Cell Programming 1
 
Sistemi Operativi: Struttura avanzata - Lezione 05
Sistemi Operativi: Struttura avanzata - Lezione 05Sistemi Operativi: Struttura avanzata - Lezione 05
Sistemi Operativi: Struttura avanzata - Lezione 05
 
LUG - Ricompilazione kernel
LUG - Ricompilazione kernelLUG - Ricompilazione kernel
LUG - Ricompilazione kernel
 
Apache Parte 1
Apache Parte 1Apache Parte 1
Apache Parte 1
 

Mehr von Majong DevJfu

9 - Architetture Software - SOA Cloud
9 - Architetture Software - SOA Cloud9 - Architetture Software - SOA Cloud
9 - Architetture Software - SOA CloudMajong DevJfu
 
8 - Architetture Software - Architecture centric processes
8 - Architetture Software - Architecture centric processes8 - Architetture Software - Architecture centric processes
8 - Architetture Software - Architecture centric processesMajong DevJfu
 
7 - Architetture Software - Software product line
7 - Architetture Software - Software product line7 - Architetture Software - Software product line
7 - Architetture Software - Software product lineMajong DevJfu
 
6 - Architetture Software - Model transformation
6 - Architetture Software - Model transformation6 - Architetture Software - Model transformation
6 - Architetture Software - Model transformationMajong DevJfu
 
5 - Architetture Software - Metamodelling and the Model Driven Architecture
5 - Architetture Software - Metamodelling and the Model Driven Architecture5 - Architetture Software - Metamodelling and the Model Driven Architecture
5 - Architetture Software - Metamodelling and the Model Driven ArchitectureMajong DevJfu
 
4 - Architetture Software - Architecture Portfolio
4 - Architetture Software - Architecture Portfolio4 - Architetture Software - Architecture Portfolio
4 - Architetture Software - Architecture PortfolioMajong DevJfu
 
3 - Architetture Software - Architectural styles
3 - Architetture Software - Architectural styles3 - Architetture Software - Architectural styles
3 - Architetture Software - Architectural stylesMajong DevJfu
 
2 - Architetture Software - Software architecture
2 - Architetture Software - Software architecture2 - Architetture Software - Software architecture
2 - Architetture Software - Software architectureMajong DevJfu
 
1 - Architetture Software - Software as a product
1 - Architetture Software - Software as a product1 - Architetture Software - Software as a product
1 - Architetture Software - Software as a productMajong DevJfu
 
10 - Architetture Software - More architectural styles
10 - Architetture Software - More architectural styles10 - Architetture Software - More architectural styles
10 - Architetture Software - More architectural stylesMajong DevJfu
 

Mehr von Majong DevJfu (20)

9 - Architetture Software - SOA Cloud
9 - Architetture Software - SOA Cloud9 - Architetture Software - SOA Cloud
9 - Architetture Software - SOA Cloud
 
8 - Architetture Software - Architecture centric processes
8 - Architetture Software - Architecture centric processes8 - Architetture Software - Architecture centric processes
8 - Architetture Software - Architecture centric processes
 
7 - Architetture Software - Software product line
7 - Architetture Software - Software product line7 - Architetture Software - Software product line
7 - Architetture Software - Software product line
 
6 - Architetture Software - Model transformation
6 - Architetture Software - Model transformation6 - Architetture Software - Model transformation
6 - Architetture Software - Model transformation
 
5 - Architetture Software - Metamodelling and the Model Driven Architecture
5 - Architetture Software - Metamodelling and the Model Driven Architecture5 - Architetture Software - Metamodelling and the Model Driven Architecture
5 - Architetture Software - Metamodelling and the Model Driven Architecture
 
4 - Architetture Software - Architecture Portfolio
4 - Architetture Software - Architecture Portfolio4 - Architetture Software - Architecture Portfolio
4 - Architetture Software - Architecture Portfolio
 
3 - Architetture Software - Architectural styles
3 - Architetture Software - Architectural styles3 - Architetture Software - Architectural styles
3 - Architetture Software - Architectural styles
 
2 - Architetture Software - Software architecture
2 - Architetture Software - Software architecture2 - Architetture Software - Software architecture
2 - Architetture Software - Software architecture
 
1 - Architetture Software - Software as a product
1 - Architetture Software - Software as a product1 - Architetture Software - Software as a product
1 - Architetture Software - Software as a product
 
10 - Architetture Software - More architectural styles
10 - Architetture Software - More architectural styles10 - Architetture Software - More architectural styles
10 - Architetture Software - More architectural styles
 
Uml3
Uml3Uml3
Uml3
 
Uml2
Uml2Uml2
Uml2
 
6
66
6
 
5
55
5
 
4 (uml basic)
4 (uml basic)4 (uml basic)
4 (uml basic)
 
3
33
3
 
2
22
2
 
1
11
1
 
Tmd template-sand
Tmd template-sandTmd template-sand
Tmd template-sand
 
26 standards
26 standards26 standards
26 standards
 

Sistemi Operativi: Thread - Lezione 08

  • 1. Svantaggi legati all'uso di processi • La gestione tradizionale dei processi può diventare molto onerosa dal punto di vista computazionale – Creazione: allocazione dello spazio di indirizzamento, e successiva popolazione – Context switch: salvataggio e ripristino degli spazi di indirizzamento (codice, dati, stack) di due processi • Con una applicazione con molti processi (server), il SO rischia di passare la maggior parte del tempo a svolgere operazioni interne di gestione, piuttosto che ad eseguire codice applicativo 1
  • 2. Svantaggi legati all'uso di processi • La nozione classica di processo ingloba due concetti ben distinti, gestiti dal SO: – Gestione delle risorse: ciascun processo ha assegnati un proprio spazio di indirizzamento (solitamente, indipendente) ed alcune risorse – Esecuzione traccia: ciascun processo esegue porzioni di codice sequenzialmente e concorrentemente con altri processi • La gestione dell'esecuzione di una traccia non comporta particolari aggravi computazionali, essendo direttamente gestita dal processore • La lentezza della gestione risiede nella complessità della gestione delle risorse del processo 2
  • 3. Separazione risorse-esecuzione • Nei SO moderni, i due concetti ora visti possono essere disaccoppiati – L'unità base di esecuzione di una traccia prende il nome di thread – L'unità base proprietaria delle risorse prende il nome di processo • Ciascun processo può essere visto come: – un contenitore di risorse – un contenitore di codice – Uno strumento per far partire tracce sequenziali (“fili” di codice, thread) di esecuzione del codice 3
  • 4. Thread • Un thread è l'insieme dei dati utilizzati per eseguire, in maniera concorrente, più tracce relative al codice di un processo • Tutti i thread generati da un processo ne condividono il codice e le risorse • In tal modo, le operazioni di gestione non toccano praticamente più lo spazio di indirizzamento! – L'aggravio di gestione si riduce sensibilmente • Un SO in grado di gestire i thread è detto multithreaded • Tutti i SO moderni supportano il multithreading 4
  • 5. Ambiente a processi (single threaded) • Ciascun processo processo file contiene tutte le PCB informazioni per dati poterlo eseguire • Ambiente single stack IP threaded: ciascun processo può codice eseguire al più una traccia traccia in • Informazioni: esecuzione – Spazio indirizzi – Risorse prenotate – Registri interni 5
  • 6. Ambiente multithreaded • Ciascun processo processo file contiene tutte le PCB informazioni per dati poterlo eseguire • Ambiente codice IP multithreaded: ogni thread esegue TCB TCB TCB tracce di codice • TCB: Thread Control IP stack IP stack IP stack Block (simile a PCB) – Registri, Stack traccia in traccia in traccia in esecuzione esecuzione esecuzione – Variabili “locali” – Stato esecuzione 6
  • 8. Benefici del multithreading • Reattività – Il blocco di un thread non inficia gli altri – Maggiore fluidità di esecuzione • Condivisione risorse – I thread condividono la memoria e le risorse del processo che li ha generati • Economia – Alloco e distruggo risorse di processo una volta • Architetture SMP – I thread eseguono in parallelo sui diversi processori – Il singolo processo non li può sfruttare 8
  • 9. Problemi del multithreading • Modello di programmazione complesso – La condivisione delle risorse e della memoria implica spesso la gestione della concorrenza degli accessi a queste ultime – Ulteriori passi di programmazione, spesso complessi • Debugging complesso – E' molto difficile riprodurre bug in presenza di accessi concorrenti alle risorse – E' spesso difficile individuare le cause del bug 9
  • 10. Applicazioni del multithreading • Quali applicazioni si lasciano implementare tramite i thread? Tutte quelle applicazioni: – che possono essere spezzate in più parti da eseguire concorrentemente/parallelamente – in cui alcune parti si bloccano spesso per fare I/ O, mentre altre no – che devono gestire eventi asincroni (bottone STOP del browser) 10
  • 11. Supporto del SO ai thread • Il SO deve fornire un supporto per la gestione dei thread – Supporto allo user level, tramite librerie di funzioni (API) per gestire n thread in esecuzione – Supporto al kernel level, tramite una astrazione di traccia di esecuzione • Le diverse implementazioni di supporto ai thread svariano da un estremo all'altro – Implementazioni puramente a livello applicativo – Implementazioni puramente a livello kernel – Implementazioni “miste” • Adozione di molteplici modelli di multithreading 11
  • 12. Modello Many-to-One (N:1) • A più supporti user level corrisponde un solo supporto kernel level – Il kernel vede una sola traccia di esecuzione, ossia solo un processo che esegue – Il processo usa delle funzionalità applicative per simulare uno scheduler di mini-processi – I mini-processi non sono noti al kernel del SO – Ciascun mini-processo è, in realtà, una astrazione per eseguire una traccia di una funzione del processo • Implementazioni: Green threads (Solaris), GNU Portable Threads, Java threads, Ruby threads 12
  • 13. Modello Many-to-One (N:1) Create, stop, schedule, Processo resume, destroy Main Thread library User space Thread Thread Thread PCB Kernel space 13
  • 14. Modello Many-to-One (N:1) • Vantaggi – Gestione efficientissima dei thread (non viene coinvolto lo scheduler del kernel) – Non richiede un kernel multithreaded per poter essere implementato • Svantaggi – Se un thread effettua una chiamata bloccante, il processo si blocca, e con esso tutti i thread – I thread sono legati allo stesso processo, e non possono eseguire su processori fisici distinti 14
  • 15. Modello One-to-One (1:1) • Ad un supporto user level corrisponde un supporto kernel level – Il kernel vede una traccia di esecuzione distinta per thread; ho l'analogo di un PCB per ciascun thread in esecuzione – Il processo usa una system call simile a fork() per invocare il meccanismo di creazione – I thread vengono schedulati dallo scheduler del kernel, come tutti gli altri processi • Implementazioni: GNU/Linux (LinuxThreads, NPTL), Windows 95/98/2000/XP/NT 15
  • 16. Modello One-to-One (1:1) Processo Thread Thread Thread Thread Main function function User space Create, f destroy Kernel PCB TCB TCB space 16
  • 17. Modello One-to-One (1:1) • Vantaggi – Se un thread effettua una chiamata bloccante, non blocca gli altri thread – I thread sono rappresentati da altrettanti TCB, e possono essere eseguiti su processori fisici distinti • Svantaggi – Gestione meno efficiente dei thread (usa lo scheduler del kernel) – Richiede un kernel multithreaded per poter essere implementato 17
  • 18. Modello Many-to-Many (N:M) • Ad N supporti user level corrispondono M supporti kernel level (N>M) – Unione del modelli 1:1 ed N:1; intende prendere il meglio dei due modelli – Il processo usa una system call simile a fork() per creare M thread kernel level – Ciascuno di questi M kernel level thread crea N/ M thread user level • Implementazioni: IRIX, HP-UX, Tru64 UNIX, Solaris (fino a V.9) 18
  • 19. Modello Many-to-Many (N:M) ProcessoCreate, stop, sched, ProcessoCreate, stop, sched, resume, destroy resume, destroy Main Main Thread Thread library library User space Thread Thread Thread Thread Thread Thread Kernel PCB TCB space Create, destroy 19
  • 20. Quando si applicano i modelli? • Modello Many-to-One – Buono per applicazioni di tipo parallelo con pochissimo I/O – Lo scheduler del kernel non le rallenta – Thread non schedulabili su più processori • Modello One-to-One – Ideale per applicazioni di tipo parallelo o distribuito con tanto I/O (server) – Mantiene elevato il grado di concorrenza – Ha soppiantato tutti gli altri modelli • Modello Many-to-Many – Concepito per applicazioni suddivise in una parte I/O (1:1) ed in una parte di calcolo (M:1) 20
  • 21. Multithreading: creazione/immagine • In un programma multithreaded la semantica delle operazioni fork() ed exec() cambia • Se un thread invoca la chiamata fork(): – può duplicare se stesso – può duplicare l'intero gruppo di thread • Se un thread invoca la chiamata exec(): – Sovrascrive l'immagine di tutti i thread e del processo invocante • Solitamente, si evita l'uso della exec() in ambiente multithreaded – Si associano i thread a funzioni che devono essere eseguite 21
  • 22. Multithreading: cancellazione • La cancellazione è l'operazione di terminazione prematura di un thread • Il thread selezionato per una cancellazione è chiamato thread bersaglio (target thread) • La cancellazione del target bersaglio può avvenire in due modalità distinte: – cancellazione asincrona: un altro thread uccide direttamente il thread bersaglio – cancellazione differita: il thread bersaglio controlla periodicamente (cancellation point) se deve terminare, in modo da uscire in maniera pulita 22
  • 23. Multithreading: gestione segnali • In ambiente single threaded, il segnale viene inviato ad un processo • In ambiente multithreaded, a quale thread va inviato il segnale? – al thread cui il segnale si riferisce – a ciascun thread (CTRL-C) – a specifici thread ♦ il primo thread che non blocca il segnale ♦ Identificato dal TID – ad un thread speciale, di controllo (Solaris 2) 23
  • 24. Multithreading: thread pool • All'aumentare del numero di flussi concorrenti, le risorse del sistema possono esaurire rapidamente • Per impedire l'esaurimento delle risorse, un software multithreaded pre-crea un insieme di thread (thread pool) – Quando viene lanciato un thread, lo si preleva dal gruppo – Quando un thread termina, lo si restituisce al gruppo – Le operazioni di creazione/distruzione sono molto più veloci – Si limita il numero di thread in esecuzione 24
  • 25. Multithreading: Thread Specific Data • In particolari circostanze, ciascun thread può necessitare di una copia privata di alcuni dati, detti dati specifici (thread locale) – Variabili “globali” per thread – Variabili “static” per thread • La maggior parte delle librerie pthread forniscono il supporto per i thread locale 25
  • 26. Modelli di programmazione • L'uso dei thread permette l'implementazione efficiente di alcuni modelli di programmazione • Modello Pipeline: – I thread eseguono “a catena”, uno dopo l'altro • Modello Master-Slave: – Il thread master coordina l'esecuzione dei thread slave (che effettuano il lavoro vero e proprio) • Modello Worker: – Tutti i thread lavorano 26
  • 27. Modelli di programmazione Pipeline M Master-Slave S S S W W Worker W W 27
  • 28. Librerie di threading • Ciascuna implementazione del supporto ai thread fornisce una libreria di funzioni (thread library) per la gestione dei thread – La libreria può fare uso nullo, parziale o completo delle funzionalità offerte dal kernel • Implementazioni: – Pthreads: standard POSIX, kernel level – Win32: kernel level – Java: user level 28
  • 29. Libreria Pthreads • Standard ANSI/IEEE POSIX 1003.1 – Gestione thread: creazione, distruzione, sincronizzazione – Gestione concorrenza: meccanismo dei mutex – Comunicazione concorrente: meccanismo per creare, distruggere e segnalare thread sulla base dei valori di specifiche variabili condizione (condition variables) • Più di 60 funzioni per gestire thread come tipi di dato opachi (pthread_t) • Concepita per i linguaggi C, C++ • Compilazione: gcc -pthread – include <pthread.h> 29
  • 30. Creazione thread • Signature: int pthread_create( pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); – Descrizione: crea un nuovo thread, eseguente la funzione start_routine con argomento arg – Ingresso: ♦ Un puntatore alla struttura thread identificante il thread da eseguire ♦ Un puntatore alla struttura “attributi” che imposta le caratteristiche del thread (NULL) ♦ Un puntatore alla funzione start_routine ♦ Un puntatore all'argomento arg 30
  • 31. Creazione thread • Signature: int pthread_create( pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); – Descrizione: crea un nuovo thread, eseguente la funzione start_routine con argomento arg – Ritorno: ♦ 0 -> tutto ok – Il TID del thread appena creato è salvato all'interno della struttura dati thread ♦ !=0 -> errore – tipicamente, le risorse del sistema sono insufficienti per la creazione di un thread 31
  • 32. Creazione thread • Un thread, a sua volta, può creare altri thread con la pthread_create() • Non esiste gerarchia o dipendenza fra I vari thread 32
  • 33. Terminazione thread • Le cause di terminazione di un thread sono molteplici – Il thread ritorna dalla funzione – Il thread invoca una chiamata di funzione pthread_exit() – Il thread è cancellato da un altro thread tramite la funzione pthread_cancel() – Il processo invocante carica un'altra immagine con la funzione exec() – Il processo invocante esce tramite la funziona exit() 33
  • 34. Terminazione thread • Signature: void pthread_exit(void *retval); – Descrizione: termina l'esecuzione del thread invocante – Ingresso: ♦ un puntatore ad una variabile in cui sarà scritto il codice di uscita del thread (potrà essere consultato tramite la pthread_join()) – Ritorno: nessuno 34
  • 35. Attributi dei thread • Ad un thread è associata una struttura dati identificante le sue proprietà (attributi): pthread_attr_t • Tale struttura contiene una maschera di bit, che rappresenta le proprietà attivate • Alcune proprietà: – Thread “joinabile” – Algoritmo di scheduling utilizzato – Scope delle variabili 35
  • 36. Attributi dei thread • Signature: int pthread_attr_init(pthread_attr_t *attr); – Descrizione: inizializza una struttura pthread_attr_t – Ingresso: ♦ un puntatore ad una struttura pthread_attr_t – Ritorno: ♦ Sempre 0 36
  • 37. Attributi dei thread • Signature: int pthread_attr_destroy (pthread_attr_t *attr); – Descrizione: resetta una struttura pthread_attr_t e rilascia le risorse allocate – Ingresso: ♦ un puntatore ad una struttura pthread_attr_t – Ritorno: ♦ Sempre 0 37
  • 38. Attributi dei thread • Signature: int pthread_set_detachstate (pthread_attr_t *attr, int detachstate); – Descrizione: imposta il flag “detached” del thread con proprietà attr al valore detachstate – Ingresso: ♦ Un puntatore ad una struttura pthread_attr_t ♦ Lo stato desiderato (PTHREAD_CREATE_JOINABLE) – Ritorno: ♦ 0: -> tutto OK ♦ !=0: un errore 38
  • 39. Attributi dei thread • Signature: int pthread_set_detachstate (pthread_attr_t *attr, int detachstate); – Descrizione: imposta il flag “detached” del thread con proprietà attr al valore detachstate – Ingresso: ♦ Un puntatore ad una struttura pthread_attr_t ♦ Lo stato desiderato (PTHREAD_CREATE_JOINABLE) – Ritorno: ♦ 0: -> tutto OK ♦ !=0: un errore 39
  • 40. Sincronizzazione thread • La sincronizzazione fra thread creante e thread avviene in maniera simile ai processi • Si utilizza la funzione pthread_join() (analogo della waitpid()) • Il thread invocante (o il processo) si blocca fino a quando un thread specificato da threadid termina • Il thread invocante (o il processo) può leggere il codice di uscita • A differenza dei processi, bisogna specificare esplicitamente che un thread sia “joinabile” 40
  • 41. Sincronizzazione thread • Come si specifica la proprietà “joinable” sui thread? • Step 1: si dichiara una variabile “attributi” di tipo pthread_attr_t • Step 2: si inizializza la variabile con la funzione pthread_attr_init() • Step 3: si imposta l'attributo “detached” con la funzione pthread_attr_setdetachstate() • Step 4: in un punto successivo, si rilasciano le risorse allocate con la funzione pthread_attr_destroy() 41
  • 43. Sincronizzazione thread • Signature: int pthread_join (pthread_t th, void **thread_return); – Descrizione: ♦ sospende l'esecuzione del thread invocante fino all'uscita del thread identificato da th ♦ Se thread_return != NULL, scrive il codice di uscita nella cella puntata da thread_return – Ingresso: ♦ un puntatore ad una struttura pthread_attr_t – Ritorno: ♦ 0: -> tutto OK ♦ !=0: un errore 43
  • 44. Concorrenza thread • Per gestire l'accesso concorrente a variabili condivise, si utilizza il costrutto dei semafori – Variabili mutex (MUTual Exclusion): interi posti a 0 (risorsa libera) o 1 (risorsa occupata) pthread_mutex_t – Ciascun mutex agisce come un lucchetto (lock) sugli altri thread che vogliono accedere alla risorsa – Due stati: ♦ LOCKED: risorsa prenotata da un thread ♦ UNLOCKED: risorsa libera – Impedisce le cosiddette corse critiche (accessi simultanei a variabili condivise, con indeterminatezza del risultato finale) 44
  • 45. Concorrenza thread • Scenario tipico di utilizzo dei mutex – Creazione ed inizializzazione di una variabile di tipo mutex – Più thread provano a prenotare la risorsa, cercando di ottenere il lock sul mutex – Un solo thread ci riesce (quello che arriva per primo) e prenota la risorsa per se – Il thread modifica la risorsa in questione – Il thread rilascia la risorsa – Un altro thread acquisisce il lock sul mutex – Il processo si ripete – Il mutex viene distrutto 45
  • 46. Concorrenza thread • Dichiarazione mutex: può avvenire in due modi distinti – Dichiarazione statica: pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER; – Dichiarazione dinamica: pthread_mutex_init() 46
  • 47. Concorrenza thread • Signature: int pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutex_attr_t *mutexattr); – Descrizione: ♦ Inizializza il mutex puntato da mutex con gli attributi puntati di mutexattr ♦ Il mutex è UNLOCKED (risorsa libera) – Ingresso: ♦ un puntatore ad una struttura pthread_mutex_t ♦ un puntatore ad una struttura pthread_mutex_attr_t – Ritorno: ♦ Sempre 0 47
  • 48. Concorrenza thread • Signature: int pthread_mutex_destroy (pthread_mutex_t *mutex); – Descrizione: ♦ Resetta lo stato del mutex puntato da mutex – Ingresso: ♦ un puntatore ad una struttura pthread_mutex_t – Ritorno: ♦ 0: -> tutto OK ♦ !=0: il mutex è attualmente bloccato 48
  • 49. Concorrenza thread • Signature: int pthread_mutex_lock (pthread_mutex_t *mutex); – Descrizione: ♦ Prova ad acquisire un lock su mutex ♦ Se mutex=UNLOCKED, lo acquisisce e torna ♦ Se mutex=LOCKED, si blocca fino a quando la risorsa non si libera – Ingresso: ♦ un puntatore ad una struttura pthread_mutex_t – Ritorno: ♦ 0: -> tutto OK ♦ !=0: mutex non inizializzato o già bloccato dallo stesso thread 49
  • 50. Concorrenza thread • Signature: int pthread_mutex_trylock (pthread_mutex_t *mutex); – Descrizione: ♦ Provaad acquisire un lock su mutex ♦ Se mutex=UNLOCKED, lo acquisisce e torna ♦ Se mutex=LOCKED, ritorna e non si blocca – Ingresso: ♦ un puntatore ad una struttura pthread_mutex_t – Ritorno: ♦ 0: -> tutto OK ♦ !=0: mutex non inizializzato, già bloccato dallo stesso thread, già bloccato da un altro thread 50
  • 51. Concorrenza thread • Signature: int pthread_mutex_unlock (pthread_mutex_t *mutex); – Descrizione: ♦ Rilascia la risorsa associata al mutex ♦ Reimposta il mutex ad UNLOCKED – Ingresso: ♦ un puntatore ad una struttura pthread_mutex_t – Ritorno: ♦ 0: -> tutto OK ♦ !=0: mutex non inizializzato, già bloccato dallo stesso thread, già bloccato da un altro thread 51
  • 52. Variabili condizione • Le variabili condizione costituiscono un ulteriore meccanismo per la sincronizzazione fra thread • Idea: associare eventi al valore di alcune variabili – Una variabile assume un valore->scatta un evento – Un'altra variabile, detta variabile condizione, viene usata per segnalare l'evento – Callback: gestione asincrona di eventi tramite invocazione di funzioni • Senza le variabili di condizione, un thread deve continuamente controllare (poll) l'arrivo di eventi, sprecando inutilmente risorse di calcolo 52
  • 53. Variabili condizione • Scenario tipico di utilizzo - variabili condizione • Tre thread: – Thread Main: thread di controllo che schedula i thread di lavoro A e B – Thread A: lavora fino ad un certo punto, poi si ferma in attesa di un evento – Thread B: lavora fino ad un certo punto, poi scatena l'evento sul quale sta aspettando A • Che funzioni eseguono i tre thread? 53
  • 54. Variabili condizione • Thread Main: – Dichiara ed inizializza (strutture) dati globali che necessitano di sincronizzazione – Dichiara ed inizializza un oggetto di tipo “variabile condizione” – Dichiara ed inizializza un mutex associato alla variabile condizione – Crea i thread A e B – Join dei thread A e B 54
  • 55. Variabili condizione • Thread A: – Lavora fino a quando non si deve interrompere, in attesa che una condizione si verifichi – Acquisisce il lock sul mutex – Si blocca (pthread_cond_wait()) fino a quando non si verifica l'evento, segnalato da un altro thread (Thread B) – pthread_cond_wait() sblocca automaticamente il mutex, che può essere utilizzato dall'altro thread per acquisire uso esclusivo sulla variabile che rappresenta l'evento – Quando arriva il segnale, Thread A si sveglia ed il mutex viene di nuovo assegnato a lui – Thread A rilascia esplicitamente il mutex 55
  • 56. Variabili condizione • Thread B: – Lavora – Acquisisce il lock sul mutex – Cambia il valore della variabile su cui è bloccato Thread A – Se il valore della variabile è tale da scatenare un evento, segnala Thread A tramite una variabile condizione – Rilascia esplicitamente il mutex 56
  • 57. Variabili condizione • Rappresentate dal tipo di dato opaco pthread_cond_t • Devono essere inizializzate prima di poter essere utilizzate • Possono specificare dei propri attributi • L'inizializzazione avviene in due modi distinti: – Inizializzazione statica: pthread_cond_t myconvar = PTHREAD_COND_INITIALIZER; – Inizializzazione dinamica: pthread_cond_init() 57
  • 58. Variabili condizione • Signature: int pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *cond_attr); – Descrizione: ♦ Inizializza la variabile condizione cond utilizzando gli attributi cond_attr (NULL per default) – Ingresso: ♦ un puntatore ad una struttura pthread_cond_t ♦ un puntatore ad una struttura pthread_condattr_t – Ritorno: ♦ Sempre 0 58
  • 59. Variabili condizione • Signature: int pthread_cond_destroy (pthread_cond_t *cond); – Descrizione: ♦ Resetta una variabile condizione cond, rilasciando le risorse che potrebbe avere allocato – Ingresso: ♦ un puntatore ad una struttura pthread_cond_t – Ritorno: ♦ 0: -> tutto OK ♦ !=0: la variabile condizione è attualmente utilizzata da un qualche thread 59
  • 60. Variabili condizione • Signature: int pthread_condattr_init (pthread_condattr_t *attr); – Descrizione: inizializza una struttura pthread_condattr_t – Ingresso: ♦ un puntatore ad una struttura pthread_condattr_t – Ritorno: ♦ Sempre 0 60
  • 61. Variabili condizione • Signature: int pthread_condattr_init (pthread_condattr_t *attr); – Descrizione: inizializza una struttura pthread_condattr_t – Ingresso: ♦ un puntatore ad una struttura pthread_condattr_t – Ritorno: ♦ Sempre 0 61
  • 62. Variabili condizione • Signature: int pthread_condattr_destroy (pthread_condattr_t *attr); – Descrizione: resetta una struttura pthread_condattr_t – Ingresso: ♦ un puntatore ad una struttura pthread_condattr_t – Ritorno: ♦ Sempre 0 62
  • 63. Variabili condizione • Signature: int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex); – Descrizione: ♦ Blocca il thread invocante fino a quando non viene segnalata la condizione cond ♦ Deve essere invocata con mutex bloccato (altrimenti un thread potrebbe segnalare la condizione prima che un altro possa ascoltarla); il mutex viene automaticamente sbloccato al termine della chiamata ♦ Quando si verifica la condizione, il thread viene svegliato e mutex viene acquisito di nuovo (ricordatevi di rilasciarlo!) 63
  • 64. Variabili condizione • Signature: int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex); – Ingresso: ♦ Un puntatore alla struttura pthread_cont_t che rappresenta la variabile condizione su cui aspettare ♦ Un puntatore alla struttura pthread_mutex_t che rappresenta il mutex associato alla variabile condizione – Ritorno: ♦ Sempre 0 64
  • 65. Variabili condizione • Signature: int pthread_cond_signal (pthread_cond_t *cond); – Descrizione: ♦ Segnala (risveglia) un altro thread in seguito al verificarsi di una data condizione ♦ Più thread possono aspettare una data condizione; pthread_cond_signal() ne risveglia solamente uno – Ingresso: ♦ Un puntatore alla struttura pthread_cont_t che rappresenta la variabile condizione su cui aspettare – Ritorno: ♦ Sempre 0 65
  • 66. Variabili condizione • Signature: int pthread_cond_broadcast (pthread_cond_t *cond); – Descrizione: ♦ Segnala (risveglia) un insieme di thread in seguito al verificarsi di una data condizione ♦ Più thread possono aspettare una data condizione; pthread_cond_broadcast() li risveglia tutti – Ingresso: ♦ Un puntatore alla struttura pthread_cont_t che rappresenta la variabile condizione su cui aspettare – Ritorno: ♦ Sempre 0 66