silberschatz, galvin and gagne 2002 7.1 operating system concepts sincronizzazione fra processi...
TRANSCRIPT
Silberschatz, Galvin and Gagne 20027.1Operating System Concepts
Sincronizzazione fra processiSincronizzazione fra processi
Background Il problema della sezione critica Semafori Problemi classici di sincronizzazione Monitor
Silberschatz, Galvin and Gagne 20027.2Operating System Concepts
BackgroundBackground
L’accesso concorrente a dati condivisi può causare incoerenza nei dati.
Per garantire la coerenza dei dati occorrono meccanismi che assicurano l’esecuzione ordinata dei processi cooperanti.
La soluzione con memoria condivisa del problema del buffer limitato garantisce la presenza contemporanea nel buffer di al più n–1 elementi. Una soluzione in cui vengano impiegati tutti gli n elementi del buffer non è banale. Si modifica il codice del produttore–consumatore Si modifica il codice del produttore–consumatore
aggiungendo una variabile aggiungendo una variabile countercounter, inizializzata, inizializzata a 0. a 0. countercounter viene incrementata ogni volta che un nuovo viene incrementata ogni volta che un nuovo
elemento viene inserito nel buffer, decrementataelemento viene inserito nel buffer, decrementata dopo dopo un’estrazione.un’estrazione.
Silberschatz, Galvin and Gagne 20027.3Operating System Concepts
Buffer limitatoBuffer limitato
Dati condivisiDati condivisi
#define BUFFER_SIZE 10#define BUFFER_SIZE 10
typedef struct typedef struct {{
. . .. . .
}} item item;;
item buffer[BUFFER_SIZE];item buffer[BUFFER_SIZE];
int in = 0;int in = 0;
int out = 0;int out = 0;
int counter = 0;int counter = 0;
Silberschatz, Galvin and Gagne 20027.4Operating System Concepts
Buffer limitatoBuffer limitato item nextProduced;item nextProduced;
while (1) while (1) {{
while (counter == BUFFER_SIZE)while (counter == BUFFER_SIZE)
; /* do nothing */; /* do nothing */
buffer[in] = nextProduced;buffer[in] = nextProduced;
in = (in + 1) % BUFFER_SIZE;in = (in + 1) % BUFFER_SIZE;
counter ++;counter ++;
}}
item nextConsumed;item nextConsumed;
while (1) while (1) {{
while (counter == 0)while (counter == 0)
; /* do nothing */; /* do nothing */
nextConsumed = buffer[out];nextConsumed = buffer[out];
out = (out + 1) % out = (out + 1) % BUFFER_SIZE;BUFFER_SIZE;
counter –counter – –;–;
}}
Processo produttoreProcesso produttore
Processo consumatoreProcesso consumatore
inin: indice della successiva posizione libera nel buffer.
outout: indice della prima posizione piena nel buffer.
Silberschatz, Galvin and Gagne 20027.5Operating System Concepts
Buffer limitatoBuffer limitato
Le istruzioni:
counter++;counter++;counter–counter– –;–;
devono essere eseguite atomicamenteatomicamente. Un’operazione è atomica quando viene completata senza subire
interruzioni. Le istruzioni di aggiornamento del contatore vengono realizzate
in linguaggio macchina come…
registerregister11 = counter = counter
registerregister11 = register = register11 + 1 + 1
counter = registercounter = register11
registerregister22 = counter = counter
registerregister2 2 = register= register22 – 1 – 1
counter = registercounter = register22
I due registri possono coincidere…
Silberschatz, Galvin and Gagne 20027.6Operating System Concepts
Buffer limitatoBuffer limitato
Se, sia il produttore che il consumatore tentano di accedere al buffer contemporaneamente, le istruzioni in linguaggio assembler possono risultare interfogliateinterfogliate.
La sequenza effettiva di esecuzione dipende da come i processi produttore e consumatore vengono schedulati.
Esempio: Esempio: inizialmente counter = 5counter = 5
T0 produttore: registerregister11 = counter = counter (register1 = 5)
T1 produttore: registerregister11 = register = register11 + 1 + 1 (register1 = 6)
T2 consumatore: registerregister22 = counter = counter (register2 = 5)
T3 consumatore: registerregister22 = register = register22 – 1 – 1 (register2 = 4)
T4 produttore: counter counter = registerregister11 (counter = 6)
T5 consumatore: countercounter = registerregister22 (counter = 4)
Il valore di countercounter sarà pari a 4 o 6, mentre dovrebbe rimanere correttamente 5 (un elemento prodotto ed uno consumato).
Silberschatz, Galvin and Gagne 20027.7Operating System Concepts
Race conditionRace condition
Race conditionRace condition: Situazioni nelle quali più processi accedono in concorrenza, e modificano, dati condivisi. L’esito dell’esecuzione (il valore finale dei dati condivisi) dipende dall’ordine nel quale sono avvenuti gli accessi.
Per evitare le corse critiche occorre che processi concorrenti vengano sincronizzatisincronizzati.
Silberschatz, Galvin and Gagne 20027.8Operating System Concepts
Problema della sezione criticaProblema della sezione critica
n processi che competono per utilizzare dati condivisi. Ciascun processo è costituito da un segmento di codice,
chiamato sezione criticasezione critica, in cui accede a dati condivisi. ProblemaProblema — assicurarsi che, quando un processo
esegue la sua sezione critica, a nessun altro processo sia concesso eseguire la propria.
L’esecuzione di sezioni critiche da parte di processi cooperanti è mutuamente esclusivamutuamente esclusiva nel tempo.
SoluzioneSoluzione — progettare un protocollo di cooperazione fra processi: Ogni processo deve chiedere il permesso di accesso alla Ogni processo deve chiedere il permesso di accesso alla
sezione critica, tramite una sezione critica, tramite una entry sectionentry section;; La sezione critica è seguita da una La sezione critica è seguita da una exit sectionexit section; il rimanente ; il rimanente
codice è non critico.codice è non critico.
Silberschatz, Galvin and Gagne 20027.9Operating System Concepts
Soluzioni al problema della sezione criticaSoluzioni al problema della sezione critica
1.1. Mutua esclusioneMutua esclusione. Se il processo Pi è in esecuzione nella sua sezione critica, nessun altro processo può eseguire la propria sezione critica.
2.2. ProgressoProgresso. Se nessun processo è in esecuzione nella propria sezione critica ed esiste qualche processo che desidera accedervi, allora la selezione del processo che entrerà prossimamente nella propria sezione critica non può essere rimandata indefinitamente.
3.3. Attesa limitataAttesa limitata. Se un processo ha effettuato la richiesta di ingresso nella sezione critica, è necessario porre un limite al numero di volte che si consente ad altri processi di entrare nelle proprie sezioni critiche, prima che la richiesta del primo processo sia stata accordata.
Si assume che ciascun processo sia eseguito ad una velocità Si assume che ciascun processo sia eseguito ad una velocità diversa da zero.diversa da zero.
Non si fanno assunzioni sulla velocità relativa degli Non si fanno assunzioni sulla velocità relativa degli nn processi. processi.
Silberschatz, Galvin and Gagne 20027.10Operating System Concepts
Primi tentativi di soluzione del problemaPrimi tentativi di soluzione del problema
Solo 2 processi, P0 e P1.
Struttura generale del processo Pi (l’altro processo è Pj ).
do {
entry section
sezione critica
exit section
sezione non critica
} while (1);
I processi possono condividere alcune variabili per sincronizzare le loro azioni.
Silberschatz, Galvin and Gagne 20027.11Operating System Concepts
Algoritmo 1Algoritmo 1 Variabili condivise:
int turnint turn;;(inizialmente (inizialmente turn = 0turn = 0).).
turn = iturn = i PPii può entrare nella propria sezione critica. può entrare nella propria sezione critica. Processo Pi
do { while (turn != i);
sezione critica turn = j;
sezione non critica } while (1);
Soddisfa la mutua esclusionemutua esclusione, ma non il progressoprogresso. Se turn=0, P1 non può entrare nella propria sezione critica, anche se P0 si trova nella propria sezione non critica.
Richiede una stretta alternanza…
Silberschatz, Galvin and Gagne 20027.12Operating System Concepts
Algoritmo 2Algoritmo 2
Variabili condivise: boolean flag[2]boolean flag[2];;
(inizialmente (inizialmente flag [0] = flag [1] = falseflag [0] = flag [1] = false).). flag [i] = trueflag [i] = true PPi i è pronto ad entrare nella propria sezione critica.è pronto ad entrare nella propria sezione critica.
Processo Pi
do {flag[ i ] = true;while (flag[ j ]);
sezione criticaflag [ i ] = false;
sezione non critica} while (1);
Soddisfa la mutua esculsionemutua esculsione, ma non il progressoprogresso. I due processi possono porre entrambi flag[i] = true, bloccandosi indefinitamente.
Silberschatz, Galvin and Gagne 20027.13Operating System Concepts
Algoritmo 3Algoritmo 3
Combina le variabili condivise degli algoritmi 1 e 2. Processo Pi
do {flag[ i ] = true;turn = j;while (flag[ j ] and turn = j);
sezione criticaflag[ i ] = false;
sezione non critica} while (1);
Sono soddisfatte tutte le condizioni. Risolve il problema della sezione critica per due processi. Pi entra nella sezione critica (progressoprogresso) al massimo dopo un’entrata da parte di Pj (attesa attesa limitatalimitata).
Silberschatz, Galvin and Gagne 20027.14Operating System Concepts
Algoritmo del fornaioAlgoritmo del fornaio
Prima di entrare nella loro sezione critica, i processi ricevono un numero. Il possessore del numero più basso entra in sezione critica.
Se i processi Pi e Pj ricevono lo stesso numero, se i < j, allora Pi viene servito per primo, altrimenti tocca a Pj.
Lo schema di numerazione genera sempre numeri non decrescenti; ad esempio, 1,2,3,3,3,3,4,5...
Notazione < ordine lessicografico (# biglietto, # processo) ((a,ba,b ) < () < (c,dc,d ), se ), se aa < < cc o se o se aa = = cc e e b b < < dd;; max (max (aa00,…, ,…, aan-1n-1) è un numero ) è un numero kk, tale che , tale che kk a aii per per ii = 0, …, = 0, …, nn – 1– 1..
Variabili condivise:boolean choosing[n];boolean choosing[n];int number[n];int number[n];
I vettori sono inizializzati rispettivamente a falsefalse e 00.
Soluzione del problema della sezione critica per n processi.
Silberschatz, Galvin and Gagne 20027.15Operating System Concepts
Algoritmo del fornaioAlgoritmo del fornaio
do { choosing[ i ] = true;number[ i ] = max(number[0], number[1], …, number [n – 1])+1;choosing[ i ] = false;for (j = 0; j < n; j++) {
while (choosing[ j ]); while ((number[ j ] != 0) && (number[ j ],j ) <
(number[ i ],i ));}
sezione criticanumber[ i ] = 0;
sezione non critica } while (1);
number[i] = 0 indica che Pi non vuole entrare in sezione critica.
Silberschatz, Galvin and Gagne 20027.16Operating System Concepts
SemaforiSemafori
I semafori sono strumenti di sincronizzazione (che causano/non causano il busy waiting ).
Il semaforo S è una variabile intera. Si può accedere al semaforo solo attraverso due
operazioni indivisibili (operazioni atomiche, primitive).
waitwait ( (SS):): while S 0 do no–op; S– –;
signalsignal ((SS):): S++;
SpinlockSpinlock
Silberschatz, Galvin and Gagne 20027.17Operating System Concepts
Sezione critica con Sezione critica con nn processi processi
Variabili condivise:semaphore mutex;semaphore mutex; // // inizialmente inizialmente mutex = 1mutex = 1
Processo Pi:
do { wait(mutex); sezione critica
signal(mutex); sezione non critica} while (1);
Gli n processi condividono un semaforo comune, mutexmutex, da mutmutual exexclusion.
Silberschatz, Galvin and Gagne 20027.18Operating System Concepts
Implementazione dei semaforiImplementazione dei semafori
Per evitare di lasciare un processo in attesa nel ciclo while si può ricorrere ad una defizione alternativa di semaforo.
Si definisce un semaforo come un record:
typedef struct { int value; struct process *L;} semaphore;
Si assume che siano disponibili due operazioni (syscall): blockblock sospende il processo che la invoca; sospende il processo che la invoca; wakeup(wakeup(PP)) riprende l’esecuzione di un processo bloccato riprende l’esecuzione di un processo bloccato PP..
Silberschatz, Galvin and Gagne 20027.19Operating System Concepts
Implementazione dei semaforiImplementazione dei semafori
Le operazioni sui semafori possono essere definite come…
waitwait((SS):):S.value– –;if (S.value < 0) {
aggiungi il processo P a S.L;block;
}
signalsignal((SS): ): S.value++;if (S.value <= 0) {
rimuovi il processo P da S.L;wakeup(P );
}
In un ambiente con un unico processore è possibile disabilitare le
interruzioni all’inizio delle operazioni wait wait e signalsignal.
|S.value| è il numero di processi in coda.
Silberschatz, Galvin and Gagne 20027.20Operating System Concepts
Semaforo: uno strumento di sincronizzazioneSemaforo: uno strumento di sincronizzazione
Si esegue B in Pj solo dopo che A è stato eseguito in Pi
Si impiega un semaforo flag inizializzato 0 Codice:
PPii PPjj
AA waitwait((flagflag))
signalsignal((flagflag)) BB
Silberschatz, Galvin and Gagne 20027.21Operating System Concepts
Deadlock e starvationDeadlock e starvation
DeadlockDeadlock — due o più processi sono in attesa indefinita di un evento che può essere generato solo da uno dei due processi in attesa.
Siano S e Q due semafori inizializzati a 1:
PP00 PP11
waitwait((SS);); waitwait((QQ););waitwait((QQ);); waitwait((SS););
signalsignal((SS);); signalsignal((QQ););signalsignal((QQ)) signalsignal((SS););
Se dopo wait(S) di P0 viene eseguita wait(Q) di P1 si ha un deadlock.
StarvationStarvation — blocco indefinito; un processo attende indefinitamente ad un semaforo, e non può essere rimosso dalla coda del semaforo su cui è sospeso.
Silberschatz, Galvin and Gagne 20027.22Operating System Concepts
Due tipi di semaforiDue tipi di semafori
Semaforo contatorecontatore — intero che può assumere valori in un dominio non limitato.
Semaforo binariobinario — intero che può essere posto solo a 0 o 1; può essere implementato più semplicemente.
Un semaforo contatore può essere realizzato per mezzo di semafori binari.
Silberschatz, Galvin and Gagne 20027.23Operating System Concepts
Problemi classici di sincronizzazioneProblemi classici di sincronizzazione
Problema del buffer limitatoProblema del buffer limitato
Problema dei lettori e degli scrittoriProblema dei lettori e degli scrittori
Problema dei cinque filosofiProblema dei cinque filosofi
Silberschatz, Galvin and Gagne 20027.24Operating System Concepts
Problema del buffer limitatoProblema del buffer limitato
Variabili condivise:semaphore full, empty, mutex;semaphore full, empty, mutex;// inizialmente full = 0, empty = n, mutex = 1
Il buffer ha n posizioni, ciascuna in grado di contenere un elemento.
Il semaforo mutexmutex garantisce la mutua esclusione sugli accessi al buffer.
I semafori emptyempty e fullfull contano, rispettivamente, il numero di posizioni vuote ed il numero di posizioni piene nel buffer.
Silberschatz, Galvin and Gagne 20027.25Operating System Concepts
Problema del buffer limitatoProblema del buffer limitato
do { … produce un elemento in nextp … wait(empty); wait(mutex); … inserisce nextp nel buffer … signal(mutex); signal(full);} while (1);
Processo produttoreProcesso produttore Processo consumatoreProcesso consumatore
do { wait(full) wait(mutex); … sposta un elemento dal buffer in nextc … signal(mutex); signal(empty); … consuma un elemento in nextc …} while (1);
Silberschatz, Galvin and Gagne 20027.26Operating System Concepts
Problema dei lettori e degli scrittoriProblema dei lettori e degli scrittori
Variabili condivise: semaphore mutex, wrt;semaphore mutex, wrt;
int readcount;int readcount; // inizialmente // inizialmente mutex = 1, wrt = 1, readcount = 0mutex = 1, wrt = 1, readcount = 0
Un insieme di dati (ad es. un file) deve essere condiviso da più processi concorrenti che possono richiedere la sola lettura del contenuto, o anche un aggiornamento.
Se due lettoriettori accedono contemporaneamente ai dati condivisi non ha luogo alcun effetto negativo, se uno scrittorescrittore accede simultaneamente ad altro processo si può avere incoerenza dell’informazione.
11o o problema dei lettori–scrittori problema dei lettori–scrittori: nessun processo lettore deve attendere, salvo che uno scrittore abbia già ottenuto l’accesso ai dati condivisi (possibilità di starvation per gli scrittori).
Silberschatz, Galvin and Gagne 20027.27Operating System Concepts
Problema dei lettori e degli scrittoriProblema dei lettori e degli scrittori
wait(wrt); … si effettua la scrittura …
signal(wrt);
Processo scrittoreProcesso scrittore Processo lettoreProcesso lettore
wait(mutex);readcount++;if (readcount == 1)
wait(wrt);signal(mutex);
… si effettua la lettura …
wait(mutex);readcount – –;if (readcount == 0)
signal(wrt);signal(mutex);
readcountreadcount conta i lettori attualmente attivi.
Silberschatz, Galvin and Gagne 20027.28Operating System Concepts
Problema dei cinque filosofiProblema dei cinque filosofi Cinque filosofi passano la vita pensando e mangiando, attorno ad una tavola
rotonda. Al centro della tavola vi è una zuppiera di riso e la tavola è apparecchiata con cinque bacchette.
Quando un filosofo pensa non interagisce con i colleghi. Quando gli viene fame tenta di impossessarsi delle bacchette che stanno alla sua destra ed alla sua sinistra. Il filosofo può prendere una sola bacchetta per volta.
Quando un filosofo affamato possiede due bacchette contemporaneamente, mangia. Terminato il pasto, appoggia le bacchette e ricomincia a pensare.
Shematizza la classe dei problemi di allocazione di risorse multiple.
Si può rappresentare ciascuna bacchetta con un semaforo.
Ogni filosofo tenta di afferrare una bacchetta con un’operazione di wait e la rilascia eseguendo signal sul semaforo appropriato.
Silberschatz, Galvin and Gagne 20027.29Operating System Concepts
Problema dei cinque filosofiProblema dei cinque filosofi
Variabili condivise: semaphore chopstick[5]; semaphore chopstick[5]; // tutti gli elementi inizializzati a 1// tutti gli elementi inizializzati a 1 Filosofo i:
do {wait(chopstick[ i ])wait(chopstick[(i+1) % 5])
…mangia …
signal(chopstick[ i ]);signal(chopstick[(i+1) % 5]);
…pensa …
} while (1);
Silberschatz, Galvin and Gagne 20027.30Operating System Concepts
Problema dei cinque filosofiProblema dei cinque filosofi
Non esclude il deadlock, ad esempio se tutti i filosofi hanno fame contemporaneamente e prendono prima la bacchetta alla loro destra.
Alcune soluzioni: Solo quattro filosofi possono essere seduti simultaneamente Solo quattro filosofi possono essere seduti simultaneamente
a tavola.a tavola. Un filosofo può prendere le sue bacchette solo se sono Un filosofo può prendere le sue bacchette solo se sono
entrambe disponibili.entrambe disponibili. Adottare una soluzione asimmetrica. Un filosofo dispari Adottare una soluzione asimmetrica. Un filosofo dispari
prende prima la bacchetta di sinistra, un filosofoprende prima la bacchetta di sinistra, un filosofo pari prende pari prende prima la bacchetta di destra.prima la bacchetta di destra.
Silberschatz, Galvin and Gagne 20027.31Operating System Concepts
MonitorMonitor È un costrutto di sincronizzazione di alto livello che permette la condivisione
sicura di un tipo astratto di dati fra processi concorrenti.monitor monitor–name{
dichiarazione delle variabili condiviseprocedure body P1 (…) {
. . .}procedure body P2 (…) {
. . .} procedure body Pn (…) {
. . .} {
codice di inizializzazione}
}
Gli operatori sono definiti dal programmatore.
I valori delle variabili definiscono lo stato di un istanza del tipo.
La mutua esclusione non deve essere codificata esplicitamente
Silberschatz, Galvin and Gagne 20027.32Operating System Concepts
MonitorMonitor
La definizione base di monitor non è sufficiente per modellare alcuni schemi di sincronizzazione…
per permettere ad un processo di attendere dentro al monitor, devono essere dichiarate apposite variabili conditioncondition
condition x, y;condition x, y; Le variabili condition possono essere usate solo in
relazione a specifiche operazioni waitwait e signalsignal. L’operazioneL’operazione
x.wait( );x.wait( );fa sì che il processo chiamante rimanga sospeso fino fa sì che il processo chiamante rimanga sospeso fino a che un diverso processo non effettui la chiamata…a che un diverso processo non effettui la chiamata…
x.signal( );x.signal( ); L’operazione L’operazione x.signalx.signal attiva esattamente un processo attiva esattamente un processo
sospeso. Se non esistono processi sospesi l’operazione sospeso. Se non esistono processi sospesi l’operazione signalsignal non ha alcun effetto. non ha alcun effetto.
Silberschatz, Galvin and Gagne 20027.33Operating System Concepts
Schema di un monitorSchema di un monitor
Silberschatz, Galvin and Gagne 20027.34Operating System Concepts
Monitor con variabili conditionMonitor con variabili condition
Silberschatz, Galvin and Gagne 20027.35Operating System Concepts
Esempio dei cinque filosofiEsempio dei cinque filosofi
monitor dp {
enum {thinking, hungry, eating} state[5];
condition self[5];void pickup(int i) void putdown(int i) void test(int i) void init( ) {
for (int i = 0; i < 5; i++)state[ i ] = thinking;
}}
Soluzione senza deadlock: al filosofo è permesso di prelevare le bacchette solo se sono entrambe disponibili. La distribuzione delle bacchette è controllata dal monitor dp.
Silberschatz, Galvin and Gagne 20027.36Operating System Concepts
Esempio dei cinque filosofiEsempio dei cinque filosofi
void pickup(int i) {state[ i ] = hungry;test[ i ];if (state[ i ] != eating)
self[ i ].wait();}
void putdown(int i) {state[ i ] = thinking;// controlla i vicini
destro e sinistrotest((i+4) % 5);test((i+1) % 5);
}
void test(int i) {
if ( (state[(i + 4) % 5] != eating) && (state[ i ] == hungry) && (state[(i + 1) % 5] != eating)) {
state[ i ] = eating;self[ i ].signal( );
}}
Silberschatz, Galvin and Gagne 20027.37Operating System Concepts
Implementazione del monitor con semaforiImplementazione del monitor con semafori
Variabili semaphore mutex; // semaphore mutex; // (inizialmente(inizialmente = 1 = 1))semaphore next; // semaphore next; // (inizialmente(inizialmente = 0 = 0))int next–count = 0;int next–count = 0;
Ciascuna procedura esterna FF viene rimpiazzata con
wait(mutex); … corpo di F ; …if (next–count > 0)signal(next)else signal(mutex);
La mutua esclusione è assicurata all’interno del monitor.
Silberschatz, Galvin and Gagne 20027.38Operating System Concepts
Implementazione del monitor con semaforiImplementazione del monitor con semafori
Per ogni variabile condition x, si ha:semaphore x–sem; // semaphore x–sem; // (inizialmente(inizialmente = 0 = 0))int x–count = 0;int x–count = 0;
Le operazioni x.wait e x.signal possono essere implementate rispettivamente come:
x–count++;if (next–count > 0) signal(next);else signal(mutex);wait(x–sem);x–count– –;
if (x–count > 0) { next–count++;
signal(x–sem);wait(next);next–count– –;
}
Silberschatz, Galvin and Gagne 20027.39Operating System Concepts
Implementazione del costrutto monitorImplementazione del costrutto monitor
Costrutto Conditional–waitConditional–wait : x.wait(c);x.wait(c); cc — espressione intera valutata quando viene eseguita — espressione intera valutata quando viene eseguita
l’operazione l’operazione waitwait.. Il valore di Il valore di c c ( (numero di prioritànumero di priorità ) viene memorizzato ) viene memorizzato
insieme al nome del processo che è stato sospeso.insieme al nome del processo che è stato sospeso. Quando viene eseguita Quando viene eseguita x.signalx.signal, il processo associato al , il processo associato al
numero di priorità più basso viene riavviato.numero di priorità più basso viene riavviato. Si controllano due condizioni per stabilire la correttezza
del sistema: I processi utente devono sempre effettuare chiamate al I processi utente devono sempre effettuare chiamate al
monitor con una sequenza corretta.monitor con una sequenza corretta. È necessario assicurare che un processo non cooperativo È necessario assicurare che un processo non cooperativo
non ignori la porta di mutua esclusione fornita dal monitor, non ignori la porta di mutua esclusione fornita dal monitor, e provi ad accedere direttamente alle variabili condivise, e provi ad accedere direttamente alle variabili condivise, senza impiegare i protocolli di accesso.senza impiegare i protocolli di accesso.