PDA

View Full Version : Programmazione concorrente - semafori


Azizel
12-07-2006, 11:11
Ciao a tutti,

Sono alle prese con un progetto universitario sulla programmazione concorrente in linguaggio c.

Il mio questito riguarda un dubbio che mi è venuto sviluppando il pogetto:
In pratica ho 5 thread (ad esempio) uguali che accedono ad un area condivisa e un thread di controllo che accede a dei dati (li legge diciamo)dei vari thread sopracitati.

Ora io uso 2 semafori s1 e s2 (uso i posix thread) e un mutex per l'accesso alle aree condivise, il primo semaforo è inizializzato a 0 e il secondo a 1.

Il corpo del thread di controllo fa una wait (s2), controlla i valori (usando la mutex) e poi fa una post(s1).

Gli altri thread invece fanno prima una wait(s1) e poi una post(s2).

In questo modo ho un funzionamento che può essere riassunto in questo modo:

t1->controllo->t2->controllo->t3->controllo e così via..

In pratica i thread fanno le proprie cose e passano il controllo al thread di controllo sequenzialmente che poi passa il controllo a prossimo thread in coda.

Ora le mie domande:

Con questo metodo (s1 a 0 e s2 a 1) la mutex per accedere all'area condivisa è inutile?(tanto i thread si "passano il testimone" sequenzialmente..o sbaglio?)

Se io mettessi s2 a 5 cosa comporterebbe?

Grazie a tutti per le eventuali risposte.


Ciao

Black imp
12-07-2006, 12:00
scusa non mi ricordo la sintassi dei semafori sotto linux anche se li conosco bene quindi rimango sul concettuale: non mi è chiaro bene il funzionamento del programma. innanzi tutto i mutex sono semafori binari: se passa 1 tutti gli altri aspettano. i semafori permettono a più thread di passare finchè non saturano il limite impostato. ora mi rispieghi la storia del 'testimone' perchè non mi è chiara... soprattutto che cosa ti è stato chiesto di fare?

il thread di controllo legge nella memoria condivisa? ma è il padre degli altri thread o è concorrente?

[edit]
ok comincio a capire la sequenza. ora non ricordo bene questo: il semaforo in linux non ha già in se stesso il meccanismo per fare passare o meno i thread? o è solo una struttura con i puntatori ai thread in attesa e un contatore ? in sostanza come ti dicevo se tu inizializzi un semaforo ad un valore massimo di 5 lui non blocca i primi 5 thread che arrivano ed entrano tutti insieme nella corsa critica. se tu vuoi una sequenza di quel tipo, in cui entra uno solo esclusivamente, ti serve soltanto un mutex e basta.

Azizel
12-07-2006, 14:49
Allora in pratica il thread di controllo è concorrente(ma potrebbe essere anche il padre è indifferente).
Ci sono questi 5 thread che devono modificare delle variabili condivise, i semafori li uso per sincronizzare il tutto con il thread di controllo, in modo che svolgano una certa azione uno per volta (anche perchè il thread di controllo è molto più veloce degli altri).
Diciamo che è simile al problema dei produttori/consumatori, solo che c'è un thread che consuma (quello di controllo, che in realtà non consuma niente ma potrebbe modificare delle variabili condivise), e 5 thread che producono.
Uso lo standard posix e quindi semaphore.h e pthread.h.

Posto un pò di pseudo codice per far capire cosa fanno ora:


sem_t s1, s2;

sem_init(&s1, 0);//inizializzo il primo semaforo a 0
sem_init(&s2, 1);//inizializzo il primo semaforo a 1

thread_controllo(){//viene lanciato per primo
wait(s2);
lock(mutex);
//controllo le variabilii degli altri thread
unlock(mutex);
post(s1);
}

thread(){//ne vengono creati 5 in sequenza
wait(s1)
lock(mutex);//aggiorno le variabili
unlock(mutex);
post(s2)
}


Questo è bene o male ciò che succede adesso. La mutex (semaforo binario per la sez critica) in questo caso è superflua giusto?

Ora l'ho fatto in questo modo per evitare starvation o deadlock.
Io devo essere sicuro che tutti i 5 thread vengano eseguiti ma allo stesso tempo che il controllo venga effettuato ogni volta che uno dei thread cambia qualcosa...
La soluzione che ho implementato io mi sembra la migliore(da un certo ordine di esecuzione ai thread), però non vorrei che fosse anche superflua..perchè secondo me in questo modo garantisco non solo la sincronizzazione ma anche la protezione della sezione critica.


Ciao

caralu
12-07-2006, 17:08
La mutex (semaforo binario per la sez critica) in questo caso è superflua giusto?


Mi sa che il lock del mutex è superfluo dato che hai inizializzato il semaforo s2 = 1
In questo modo si può produrre (e consumare) un solo elemento per volta sul buffer condiviso.
Il lock del mutex ha senso quando inizializzi il tuo semaforo ad N, per far produrre in modo indipendente dal consumatore un numero di "prodotti" minore o uguale a N.

Black imp
12-07-2006, 17:31
come ti dicevo un mutex E' un semaforo che fa passare un solo thread; si chiama semaforo binario. quindi se già usi due semafori inizializzati in quel modo cioè in modo che di fatto solo un thread può entrare, il mutex è superfluo. di più: se tu vuoi alternare una volta il controllore e una volta gli altri thread, e i thread non devono appunto mai essere eseguiti insieme, ti bastano due mutex senza usare semafori. l'unico problema è che non mi ricordo se i mutex si possono inizializzare per averne in sostanza uno verde e uno rosso come hai giustamente fatto tu con i due semafori. in ogni caso concordo anch'io che il mutex è superfluo. se inizializzassi a 5 s2,il controllore potrebbe entrare le prime 5 - o 6 non ricordo se il semaforo deve essere >=0 oppure >0 -volte contemporaneamente ad un altro thread e non sarebbe bello. se inizializzassi a 4 s1 invece 4 thread entrerebbero subito - oltre al controllore - e solo il 5 aspetterebbe la terminazione del controllore - oppure entrerebbero tutti nel caso che il semaforo controlli come detto prima la condizione >=0 ... insomma il concetto è quello :D -

cnque scusa ma scritti così i thread muoiono subito dopo la prima esecuzione senza un ciclo :) non so se è quello che vuoi però sicuramente almeno il thread di controllo deve essere eseguito più volte quindi ci vuole un ciclo.

Azizel
12-07-2006, 18:10
Grazie a tutti per le risposte ;) Ora ciò capito qualcosa in più...

cnque scusa ma scritti così i thread muoiono subito dopo la prima esecuzione senza un ciclo non so se è quello che vuoi però sicuramente almeno il thread di controllo deve essere eseguito più volte quindi ci vuole un ciclo.

Sisi li ci va un ciclo ovviamente, ho fatto in fretta per far capire come erano messi i semafori.
Il mutex del posix thread è si un semaforo binario, però allo stesso tempo ha delle limitazioni (il lock può essere rilasciato solamente dal thread che l'ha chiamato!).

Comunque caralu ho letto il tuo thread precedente e mi sa che stiamo facendo lo stesso progetto... :D
Sto facendo una specie di space invaders anch'io con ncurses e i thread...
Semplicemente la mia idea per sincronizzare gli alieni che si muovono e il giocatore è quella di eseguire: giocatore - controllo - alieno - controllo - alieno - controllo - alieno e così via....dove i thread del giocatore e dell'alieno muovono le coordinate e disegnano le astronavi (e muovono staticamente anche i propri missili..senza creare altri thread che appesantiscono e rallentano purtroppo) e controllo fa il check delle collisioni (ecco perchè devo fare in modo che ogni volta che cambia qualcosa ci sia il controllo!!)

Ciao

caralu
12-07-2006, 18:24
Comunque caralu ho letto il tuo thread precedente e mi sa che stiamo facendo lo stesso progetto... :D
Sto facendo una specie di space invaders anch'io con ncurses e i thread...
Semplicemente la mia idea per sincronizzare gli alieni che si muovono e il giocatore è quella di eseguire: giocatore - controllo - alieno - controllo - alieno - controllo - alieno e così via....dove i thread del giocatore e dell'alieno muovono le coordinate e disegnano le astronavi (e muovono staticamente anche i propri missili..senza creare altri thread che appesantiscono e rallentano purtroppo) e controllo fa il check delle collisioni (ecco perchè devo fare in modo che ogni volta che cambia qualcosa ci sia il controllo!!)

E si, mi sa proprio che stiamo facendo lo stesso progetto! :-)
Io al controllo (come puoi vedere dal codice che ho postato) faccio aggiornare tutti gli oggetti in movimento, però ad ogni oggetto associo un thread (un thread per ciascuna bombaNave, bombaAliena, nave, e alieni) creato nelle rispettive funzioni...
Il problema che sto avendo è quello che nel gestire i diversi array condivisi di ciascun oggetto ho implementato molti semafori e questo mi causa una situazione di stallo..Non riesco a trovare dove sia questo maledetto deadlock!
Tu hai fatto un'array per ogni struttura diversa oppure hai messo tutto in un'unico array condiviso??
(puoi rispondere pure nel mio post, mi sa che è più attinante all'argomento!)