Esercizi sulla sincronizzazione

Documenti analoghi
Sincronizzazione fra processi

Esercizio sul Monitor. Ponte con utenti grassi e magri 11 Novembre 2013

Sistemi Operativi (M. Cesati)

Esercizi di utilizzo del semaforo semplice di competizione per l'uso di una risorsa comune

Monitor pthreads. Esercizio

Thread: sincronizzazione Esercitazioni del 09 Ottobre 2009

Il costrutto monitor

Linuxthreads: esercizio

Sistemi operativi - Concetti ed esempi -Settima edizione

Sistemi Operativi L-A. Esercizi 14 Giugno Esercizio monitor

Perche le CPU multicore

SC che operano su thread. pthread_create() etc...

SEMAFORI SEMAFORI. Sul semaforo sono ammesse solo due operazioni (primitive)

Sistemi Operativi. Lezione 7 Comunicazione tra processi

Semafori. Semafori classici con i thread POSIX 2

Soluzioni ai problemi di Mutua Esclusione Primitive di sincronizzazione. Soluzioni ai problemi di Mutua EsclusionePrimitive di sincronizzazione

Corso di Laboratorio di Sistemi Operativi

I thread nel sistema operativo LINUX: Linuxthreads

Java Virtual Machine. Indipendenza di java dalla macchina ospite. I threads in Java

Introduzione al Multithreading

Processi programma processo processo Stati di un processo Attesa di caricamento new Pronto ( ready ) Esecuzione running Waiting ( in Attesa )

Decima Esercitazione. Accesso a risorse condivise tramite Monitor Java

Le risorse. Alcune definizioni

Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A Pietro Frasca.

Meccanismi di sincronizzazione: Semafori e Monitor

Sincronizzazione dei processi

SISTEMI OPERATIVI. Sincronizzazione in Java (Monitor e variabili condizione in Java)

ESERCIZIO SincrAmbGlob-1

Monitor. Le procedure entry sono le sole operazioni che possono essere utilizzate dai processi per accedere alle variabili comuni.

Relazione tra thread e processi

Realizzazione di Politiche di Gestione delle Risorse: i Semafori Privati

I Thread in Java e POSIX

Il costrutto monitor [Hoare 74]

Introduzione. Meccanismi di sincronizzazione: Semafori e Monitor. Semafori - Definizione. Semafori - Descrizione informale

progam ponteasensounicoalaternato ; type dir = ( nord, sud );

Corso di Linguaggi di Programmazione

Esercizio di Sincronizzazione tra Processi: Ponte a Senso Unico Alternato con Capacità Limitata

SISTEMI OPERATIVI. Sincronizzazione in Java (Semafori e barriere) Patrizia Scandurra (MODULO DI INFORMATICA II) LABORATORIO

Esercitazioni 7 e 8. Bounded Buffer con sincronizzazione Java (1)

Il costrutto monitor [Hoare 74]

Cooperazione tra Processi

Lab. di Sistemi Operativi - Esercitazione n 9- -Thread-

ACSO Programmazione di Sistema e Concorrente

ELEMENTI DI INFORMATICA L-B. Ing. Claudia Chiusoli

Esercitazione 15. Il problema dello Sleeping Barber

Lab 4: Locks, Condition Variables in Java

Ricerca binaria (o dicotomica) di un elemento in un vettore

Sistemi Operativi T. Esercizi

Capitolo 7: Sincronizzazione

Sincronizzazione tra processi

Informatica 3. Informatica 3. LEZIONE 6: Il controllo dell esecuzione. Lezione 6 - Modulo 1. Errori durante l esecuzione. Il controllo dell esecuzione

CAPITOLO 24 I MONITOR

Sistemi operativi Sincronizzazione fra processi

Comunicazione tra processi: pipe Le pipe sono un meccanismo UNIX di Inter Process Communication (IPC)

ERRATA CORRIGE. void SvuotaBuffer(void); void SvuotaBuffer(void) { if(getchar()!=10) {svuotabuffer();} }

Sommario. G. Piscitelli

PRINCIPI DI SISTEMI OPERATIVI

Sistemi Operativi Esercizi Ricapitolazione. Docente: Claudio E. Palazzi

Processi parte V. Processi parte V. Sincronizzazione dei processi mediante monitor: Sintassi Funzionamento Implementazione

SOLUZIONE. <l auto arriva all ingresso I> while PostiDisponibili == 0

Elementi lessicali. Lezione 4. La parole chiave. Elementi lessicali. Elementi lessicali e espressioni logiche. Linguaggi di Programmazione I

Java threads (2) Programmazione Concorrente

Problema: ricerca di un elemento

Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A Pietro Frasca.

Sistemi operativi Modulo II I semafori 2 Select

Corso di Programmazione Concorrente Processi. Valter Crescenzi

Le strutture di controllo in C++

System Call per la gestione dei semafori in Linux. Semafori: modello concettuale. Creazione ed inizializzazione di un semaforo

3.2 Concorrenza, parallelismo e parallelismo reale

Implementazione dei monitor tramite semafori Attesa condizionale Sincronizzazione nei sistemi operativi reali Transazioni atomiche

Esercitazione 6. Array

Monitor. Introduzione. Struttura di un TDA Monitor

Sincronizzazione. Soluzioni hardware Stefano Quer Dipartimento di Automatica e Informatica Politecnico di Torino

Sistemi Operativi. Lez. 13: primitive per la concorrenza monitor e messaggi

Cognome Nome Matricola Postazione PC. Corso di Laurea in Ingegneria Gestionale Esame di Informatica - a.a Gennaio 2015

Sincronizzazione e comunicazione tra processi in Unix. usati per trasferire ad un processo l indicazione che un determinato evento si è verificato.

Esercizi Esercizi Università di Salerno

Informatica 1. Prova di recupero 21 Settembre 2001

Politecnico di Torino Sede di Alessandria Corso di informatica Programmazione in c: introduzione. e mail: sito: users.iol.

Interprocess communication: Pipe

SmallShell Piccolo processore comandi

Processi e thread. Dipartimento di Informatica Università di Verona, Italy. Sommario

18 - Vettori. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Il descrittore di processo (PCB)

Corso di Laurea in Ingegneria Gestionale Esame di Informatica a.a luglio 2011

DTI / ISIN / Titolo principale della presentazione. La cena dei filosofi. Amos Brocco, Ricercatore, DTI / ISIN. 14 maggio 2012

SISTEMI OPERATIVI 3 febbraio 2014 corso A nuovo ordinamento e parte di teoria del vecchio ordinamento indirizzo SR

Ingegneria del Software

Sistemi Operativi Esercizi Sincronizzazione

Il sistema operativo LINUX Semafori. Semaforo. Sommario. Sommario. Uso delle pipe. Gestione di semafori tramite pipe. Sistemi operativi Modulo II

AXO. Operativo. Architetture dei Calcolatori e Sistema. programmazione di sistema

Introduzione ai puntatori in C Definizione

14 - Metodi e Costruttori

ESERCIZI DI PROGRAMMAZIONE C IN AMBIENTE UNIX

Processi e thread. Concetto di processo

Esercizi di Algoritmi e Strutture Dati

Programmazione Orientata agli Oggetti in Linguaggio Java

ESERCITAZIONE 5!! 7 dicembre 2016!! Programmazione concorrente in ADA!!

Elementi di Informatica

I THREAD. thread 2. thread 1

Transcript:

Esercizi sulla sincronizzazione Problema dei lettori e degli scrittori Semafori: Lettori scrittori con priorità agli scrittori Monitor: Produttori consumatori Il conto bancario cointestato A cena con i cannibali Variabili condizione Tre a uno Processo lettore sem_wait(mutex); numlettori++; if (numlettori == 1) sem_signal(mutex); si effettua la lettura sem_wait(mutex); numlettori ; if (numlettori == 0) sem_signal(mutex); Processo scrittore si effettua la scrittura Priorità dei lettori 6.1 6.2 Lettori scrittori con priorità agli scrittori Ogni lettore che vuole leggere è accettato, a meno che uno scrittore chiede di entrare: in questo caso viene inibito l'ingresso ai lettori successivi; Un solo lettore inibisce gli scrittori e il primo degli scrittori che entra inibisce ogni altra lettura e scrittura. Lo scrittore deve utilizzare: un semaforo lettura (inizialmente 1) che blocca i lettori mentre gli scrittori accedono alla risorsa una variabile numscrittori che controlla il semaforo lettura un semaforo mutex1 (inizialmente 1) che controlla l'accesso alla variabile numscrittori un semaforo scrittura (inizialmente 1) che assicura l'accesso esclusivo in scrittura alla risorsa. Processo scrittore numscrittori++; if (numscrittori == 1) sem_wait(lettura); si effettua la scrittura numscrittori ; if (numscrittori == 0) sem_signal(lettura); 6.3 6.4 Lettori scrittori con priorità agli scrittori Ogni lettore che vuole leggere è accettato, a meno che uno scrittore chiede di entrare: in questo caso viene inibito l'ingresso ai lettori successivi; Un solo lettore inibisce gli scrittori e il primo degli scrittori che entra inibisce ogni altra lettura e scrittura. Il lettore deve utilizzare: un semaforo unoallavolta (inizialmente 1) che permette ad un solo lettore di accodarsi su lettura una variabile numlettori che controlla il semaforo scrittura un semaforo mutex2 (inizialmente 1) che controlla l'accesso alla variabile numlettori Processo scrittore numscrittori++; if (numscrittori == 1) sem_wait(lettura); si effettua la scrittura numscrittori ; if (numscrittori == 0) sem_signal(lettura); Processo lettore sem_wait(unoallavolta); sem_wait(lettura); sem_wait(mutex2); numlettori++; if (numlettori == 1) sem_signal(mutex2); sem_signal(lettura); sem_signal(unoallavolta); si effettua la lettura sem_wait(mutex2); numlettori--; if (numlettori == 0) sem_signal(mutex2); 6.5 6.6

Produttori consumatori Il conto bancario cointestato var buffer: array[0..n-1] of item; in, out: 0..n-1; size: 0..n; empty, full: condition; Procedure body Consumatori (var x:item); if size = 0 then empty.wait(); x := buffer[out]; out:=(out + 1) mod n; size:=size-1; full.signal(); Procedure body Produttori (x: item); if size = n then full.wait(); buffer[in]:=x; in:=(in+1) mod n; size:=size+1; empty.signal(); size:=0; in:=0; out:=0; end Un conto bancario è condiviso tra più persone. Ciascuna può depositare o prelevare soldi dal conto, ma il saldo non deve mai diventare negativo. Se una persona vuole prelevare e ci sono soldi a sufficienza, lo fa aggiornando il saldo, altrimenti resta in attesa che il saldo renda possibile il prelievo e, non appena c è stato un deposito: avverte le eventuali altre persone in attesa e cerca di effettuare il prelievo. Quando una persona deposita, avverte un altra eventuale persona in attesa che c è stato un deposito. Scrivere un monitor con le funzioni prelievo e deposito per risolvere questo problema. 6.7 6.8 Dati locali: var saldo: integer; sosp: condition; n-sosp: integer; Procedure body prelievo(cifra: integer) var presi: boolean; presi := false; repeat if saldo > cifra: then saldo := saldo - cifra; presi := true; else n-sosp := n-sosp + 1; sosp.wait(); if n-sosp > 0 then n-sosp := n-sosp -1; sosp.signal(); until presi; Il conto bancario cointestato 6.9 Procedure body deposito(cifra: integer) saldo := saldo + cifra; if n-sosp > 0 then n-sosp := n-sosp -1; sosp.signal(); saldo := 0; n-sosp := 0; A cena con i cannibali Una tribù di N cannibali mangia in comune da una pentola che può contenere fino a M (M < N) porzioni di stufato di missionario. Quando un cannibale ha fame controlla la pentola: Se non ci sono porzioni, sveglia il cuoco ed aspetta che questo abbia riempito di nuovo la pentola. Se la pentola contiene almeno un pasto, si mette in attesa di essere servito. Il cuoco controlla inizialmente che ci siano delle porzioni: Se ci sono si addormenta, altrimenti, cuoce M porzioni e le serve ai cannibali in attesa. Si descriva una soluzione che utilizzi un monitor e si delineino le procedure riempi e servi. 6.10 A cena con i cannibali La struttura dei processi cannibale e cuoco è la seguente: repeat serviti <mangia> until false end Scrivere un monitor (con procedure serviti e riempi) che controlli tale interazione. Il cuoco deve essere svegliato solo quando la pentola è vuota. 6.11 repeat riempi until false end Dati locali: var pasti: 0..M; #pasti cuoco_addormentato: boolean; cannibale_affamato: integer; cannibale, cuoco: condition; Procedure entry serviti() if pasti = 0 then if cuoco_addormentato then cuoco_addormentato := false; cuoco.signal(); else cannibale_affamato++; cannibale.wait(); pasti := pasti -I; A cena con i cannibali 6.12 Procedure entry riempi() if pasti > 0 then cuoco_addormentato := true; cuoco.wait(); pasti := M; while cannibale_affamato > 0 do cannibale_affamato- -; cannibale.signal(); if pasti = 0 then pasti := M; pasti := 0; cuoco_addormentato := false; cannibale_affamato := 0;

Variabili condizione La variabili condizione permettono ad un thread di attendere l occorrenza di un evento. Quando un altro thread causerà l occorrenza di tale evento, uno o più thread in attesa riceveranno un segnale e si risveglieranno. mutex unlocked? Y condition met? Y do work unlock mutex Variabili condizione La variabili condizione hanno tre componenti: la variabile condizione, un mutex associato, un predicato. Il programmatore ha il compito di di definire tutte e tre le componenti: Il predicato è la condizione (o il valore) che un thread controllerà per determinare se deve attendere; il mutex è il meccanismo che protegge il predicato; la variabile condizione è il meccanismo con cui il thread attende il verificarsi della condizione. block until unlocked N The mutex is reacquired after the condition is signaled. This way, when the predicate is evaluated, it will have a consistent state. N wait/unlock mutex lock mutex This is an atomic operation, meaning that a thread cannot be context switched in the middle of this operation. The condition is signaled here. 3.13 3.14 Attendere una condizione Segnalare una condizione Un thread può attendere su una variabile condizione per un tempo specificato o indefinitamente. Queste funzioni rilasciano il mutex associato prima di bloccare e lo riacquisiscono prima di ritornare, permettendo l accesso al mutex da altri thread. Quando la condizione si verifica, si può risvegliare almeno un thread in attesa con pthread_cond_signal() Se si vogliono risvegliare tutti i thread in attesa si utilizza pthread_cond_broadcast() pthread_cond_timedwait() If the condition is not signaled in Xamount of time, return an error. pthread_cond_wait() or wait indefinately pthread_cond_signal() pthread_cond_broadcast() wake up one thread wake up all threads Threads waiting on a condition variable: 3.15 3. Esempio Esempio Si considerino due variabili condivise x e y, protette da un mutex mut e una variabile condivisa cond che viene segnalata ogni volta che x > y int x,y; pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond = PTHREAD_COND_INITIALIZER; Per aspettare fino a che x è più grande di y si usa: while (x <= y) pthread_cond_wait(&cond, &mut); /* operate on x and y */ Modifiche di x e y che possono rendere x più grande di y devono segnalare la condizione, se necessario: /* modify x and y */ if (x > y) pthread_cond_broadcast(&cond); 3.17 3.18

Esempio Modifiche di x e y che possono rendere x più grande di y devono segnalare la condizione, se necessario: /* modify x and y */ if (x > y) pthread_cond_broadcast(&cond); Per aspettare fino a che x è più grande di y si usa: while (x <= y) pthread_cond_wait(&cond, &mut); /* operate on x and y */ #include <pthread.h> #include <stdio.h> Esempio #include <unistd.h> #include <errno.h> #include <stdlib.h> extern void fatal_error(int err_num, char *func); #define check_error(return_val, msg) \ if (return_val!= 0) fatal_error(return_val, msg); /* Creazione di due thread che: - dopo un intervallo di tempo casuale, - aggiornano metà elementi di un array condiviso con il proprio pid. Si impone un lock in modo da avere - l'accesso esclusivo all array - l'aggiornamento dell'indice dell'array Si usa una variabile condizione per avere: - una alternanza che faccia entrare il primo tre volte di seguito, il secondo una*/ /* la variabile da condividere e' un vettore di pid */ int condivisa[] = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0; int ncondivisa, cont; /* il lock per regolare l'accesso alla memoria condivisa */ pthread_mutex_t CondMutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t Cond = PTHREAD_COND_INITIALIZER; 3.19 /* aggiornatore casuale */ void *primo ( int dim); 3.20 void secondo ( int dim); int main() pthread_t tid1,tid2; int retcode, k, dim; dim=sizeof(condivisa)/sizeof(int); ncondivisa=0; cont=0; retcode=pthread_create(&tid1,null,(void *(*)()) primo,(void *)dim); check_error(retcode, create failed"); retcode=pthread_create(&tid2,null,(void *(*)())secondo,(void*)dim); check_error(retcode, create failed"); /* attende la terminazione di entrambi i thread */ retcode = pthread_join(tid1,null); check_error(retcode, join failed"); retcode = pthread_join(tid2,null); check_error(retcode, join failed"); for(k=0; k<dim; k++) printf("condivisa[%d]=%d\n", k,condivisa[k]); exit(0); void * primo (int dim) 3.21 exit(0); void * primo (int dim) int sl; int test=1; srand(getpid()); while( test ) sl = 1+(int) (3.0*rand()/(RAND_MAX+1.0)); pthread_mutex_lock( &CondMutex ); if ( ncondivisa >= dim ) test=0; else sl = 1+(int) (2.0*rand()/(RAND_MAX+1.0)); condivisa[ncondivisa]=getpid(); ncondivisa++; cont++; if ( cont > 2 ) pthread_cond_signal ( &Cond ); pthread_mutex_unlock( &CondMutex ); return( (void *) NULL); void * secondo (int dim) 3.22 return( (void *) NULL); void * secondo (int dim) int sl; int test=1; srand(getpid()); while( test ) sl = 1+(int) (3.0*rand()/(RAND_MAX+1.0)); Vol. 9 n. 1 Jan. 1966 pthread_mutex_lock( &CondMutex ); if ( ncondivisa >= dim ) test=0; else while (!( cont > 2) ) pthread_cond_wait (&Cond, &CondMutex); cont=0; sl = 1+(int) (2.0*rand()/(RAND_MAX+1.0)); condivisa[ncondivisa]=getpid(); ncondivisa++; pthread_mutex_unlock( &CondMutex ); return( (void *) NULL); 3.23 6.24

flag [ i ] := true; while ( turn!= i ) while ( flag [ 1-i ] ); turn := i flag [ i ] := false; while(1); Perché non funziona? (Problema tratto da Stallings p. 267) while(1); while(1); 1 26 3 4 5 6.25 6.26 while(1); 8 9 10 while(1); 7 while(1); 10 while(1); 7 11 6.27 6.28 while(1); 10 while(1); 12 while(1); 13 while(1); 12 flag [1] = false flag [1] = false 6.29 6.30

while(1); 13 while(1); 14 12 while(1); 13 while(1); 14 15 flag [1] = false 6.31 6.32 while(1); 17 while(1); while(1); 17 while(1); turn = 0 6.33 6.34 while(1); 19 18 20 while(1); while(1); while(1); turn = 0 6.35 6.36