View Full Version : [JAVA] sincronizzare thread
pumppkin
17-04-2008, 18:21
Ciao, sto facendo un esercizio sulla sincronizzazione dei threads in ambiente java...praticamente la situazione è questa: ho un server che gestisce l'arrivo di più thread; lo scopo dell'esercizio è quello di simulare la vendita di biglietti di un locale. Io nel thread avviato dal client arrivato c'è una chiamata ad un metodo statico, la chiamata al metodo avviene nel metodo run() del thread, che non fa altro che sottrarre il num di biglietti disponibili con il num di biglietti richiesti dal client...a questo punto dovrei gestire la sincronizzazione tra i thread..dovrei fare in modo che i thread eseguono questa sottrazione senza letture "sbagliate" cioè devo visualizzare il num di posti disponibili corretto...io ho scritto il metodo che effettua la sottrazione come synchronized ma solo questo non credo che basta. Non so se e dove andare ad inserire i metodi wait() e notify().
Questa è una parte del codice:
//all'interno del metodo run() del thread
richiestaClient = fromClient.readLine();
ServerLocale.Posti(richiestaClient);
ToClient.writeBytes("prenotazione effettuata");
...
//il metodo Posti si trova all'interno della classe principale...quella che gestisce l'arrivo dei thread
static int posti = 100;
synchronized static int Posti(String richiestaCliente){
posti = posti - Integer.parseInt(richiestaCliente);
return posti;
}
wingman87
17-04-2008, 19:18
Dov'è che visualizzi il numero di posti disponibili? Come mai non credi che basti?
pumppkin
17-04-2008, 21:09
in effetti provando senza wait() e notify() funziona senza problemi...però stavo pensando una cosa...secondo te se due thread prenotano contemporaneamente i biglietti non si verifica nessun problema di lettura?...scusa ma sono alle prime armi con la programmazione concorrente...
banryu79
18-04-2008, 09:03
Non vorrei dire una "fregnaccia" ma:
se la variabile statica che tiene traccia del numero di biglietti, il metodo che scrive sulla variabile e il metodo che legge la variabile stessero tutti e tre dentro la stessa classe e fossero synchronized allora appena uno di questi due metodi venisse invocato da un thread, quel thread otterrebbe il lock sull'istanza della classe, di fatto bloccando tutti gli altri eventuali thread, sia in lettura (tramite il metodo apposito) che in scrittura.
...
Azz da qualche parte avevo una guida molto ben fatta e chiara circa il threading in Java, se la trovo te la posto.
nuovoUtente86
18-04-2008, 09:31
Il metodo synchronized a quello serve: ad accodare eventuali chiamate multiple garantendo l' accesso univoco alla risorsa! Piu' che altro ormai tale meccanismo di mutua esclusione con la versione 6 di java è abbandonato in favore del meccanismo di lock().
In pratica basta racchiudere le istruzioni della sezione critica tra le istruzioni
lock.lock();
..............................
.............................
lock.unlock();
ovviamente lock è una variabile della classe Lock inizializzata dinamicamente ad una sua realizzazione concreta.
Detto questo non si capisce bene come tu effettui la prenotazione......il meccanismo deve funzionare pressochè cosi:
-ogni thread conosce il Server di prenotazione
-il server esporta i metodi di prenotazione che per forza di cose devono essere bloccati in mutua esclusione
-ogni thread effettua le chiamate di prenotazione sul server
Il thread deve credere di essere da solo ,mentre apunto il server deve preoccuparsi della giusta sincronizzazione degli accessi.
Inoltre non ha molto senso utilizzare variabili e metodi statici in questo caso.Il server dovrebbe presumibilmente essere in unica istanza.Da considerare anche l' utilizzo di variabili statiche potrebbe essere pericoloso ai fini della sincronizzazione anche se hai ben evitato questo problema con static synchronized.
ziociccio07
18-04-2008, 13:10
ma potrebbe fare una cosa del genere:
//il metodo Posti si trova all'interno della classe principale...quella che gestisce l'arrivo dei thread
static int posti = 100;
synchronized static int Posti(String richiestaCliente){
if (posti<richiestaCliente) try ....wait();
posti = posti - Integer.parseInt(richiestaCliente);
return posti;
notifyall();
}
nuovoUtente86
18-04-2008, 13:15
ma potrebbe fare una cosa del genere:
//il metodo Posti si trova all'interno della classe principale...quella che gestisce l'arrivo dei thread
static int posti = 100;
synchronized static int Posti(String richiestaCliente){
if (posti<richiestaCliente) try ....wait();
posti = posti - Integer.parseInt(richiestaCliente);
return posti;
notifyall();
}
Questo ha un senso qualora la risorsa sia rinnovabile,che ne so i tavoli che si liberano in un ristorante o per passare all' ambito informatico la lettura e utilizzo in maniera esclusiva di un file.Questo esercizio ha l' unico scopo di effettuare la prenotazione e quindi se non ci sono piu posti il metodo dovrebbe lanciare un' eccezione oppure piu banalmente restituire una booleana.
Inoltre per il tipo di situazione cui si attende fintanto che una certa condizione è vera esiste l' apposito strumento delle Condition utilizzato insieme appunto ai lock.
nuovoUtente86
18-04-2008, 13:27
ovviamente la condition va protetta da un ciclo while che verifichi che il thread risvegliato o corrente abbia il diritto di eseguire le istruzioni del metodo.Si avrà qualcosa del genere
while(condizione non verificato)
condition.await();
........................
........................
.......................istruzioni
signal()/signalAll();
ziociccio07
18-04-2008, 13:41
Questo ha un senso qualora la risorsa sia rinnovabile,che ne so i tavoli che si liberano in un ristorante o per passare all' ambito informatico la lettura e utilizzo in maniera esclusiva di un file.Questo esercizio ha l' unico scopo di effettuare la prenotazione e quindi se non ci sono piu posti il metodo dovrebbe lanciare un' eccezione oppure piu banalmente restituire una booleana.
Inoltre per il tipo di situazione cui si attende fintanto che una certa condizione è vera esiste l' apposito strumento delle Condition utilizzato insieme appunto ai lock.
logico.
se i biglietti finiscono....sò finiti.
ho scritto solo un estratto di codice,per indicargli che se la risorsa è KO allora si ha wait/errore/...,mentre altrimenti "consuma" e notifica/segnala agli altri che ha consumato.
nuovoUtente86
18-04-2008, 13:49
logico.
se i biglietti finiscono....sò finiti.
ho scritto solo un estratto di codice,per indicargli che se la risorsa è KO allora si ha wait/errore/...,mentre altrimenti "consuma" e notifica/segnala agli altri che ha consumato.
ma nel caso specifico dei biglietti l' unica coda è quella sul lock esplicito o implicito che sia e viene risvegliata all' unlock in caso e all' uscita dal metodo sincronizzato nell' altro!Ovviamente in altri contesti bisogna attendere ficnhe non si ha il diritto di eseguire e logicamente si usano i vari wait(),condition ecc
ziociccio07
18-04-2008, 14:02
si,certo.
a stò punto,potrebbe crearsi un nuovo Monitor,che ha la sola signal,senza wait,e che realizza la signal con dei semafori binari a coda,richiamando i metodi p() e v().
e quindi usa stò monitor.
elaboriosa,ma efficace.
nuovoUtente86
18-04-2008, 14:23
si,certo.
a stò punto,potrebbe crearsi un nuovo Monitor,che ha la sola signal,senza wait,e che realizza la signal con dei semafori binari a coda,richiamando i metodi p() e v().
e quindi usa stò monitor.
elaboriosa,ma efficace.
ma a che serve???
gia funziona con syncronized o al limite con i lock.Perchè complicarsi la vita?
ziociccio07
18-04-2008, 14:27
appunto.
per questo ho detto che è elaboriosa. :D
pumppkin
18-04-2008, 16:20
intanto grazie di tutte queste risposte e proposte....comunque alla fine come avevo detto prima il problema si è risolto con il solo synchronized...inoltre dopo l'ho fatto anche con wait() e notifyAll()...so che potrebbero anche non servire tutte queste cose però l'esercizio richiedeva di sincronizzare i threads...quindi...penso che vada bene così...grazie
nuovoUtente86
18-04-2008, 18:02
intanto grazie di tutte queste risposte e proposte....comunque alla fine come avevo detto prima il problema si è risolto con il solo synchronized...inoltre dopo l'ho fatto anche con wait() e notifyAll()...so che potrebbero anche non servire tutte queste cose però l'esercizio richiedeva di sincronizzare i threads...quindi...penso che vada bene così...grazie
Attento utilizzare wait e notifyAll dove non servono è un errore oltra che può creare malfunzionamenti.
pumppkin
18-04-2008, 19:13
penso di non aver commesso errori nell'utilizzo wait() e notifyAll()...praticamente ho creato due nuovi metodi lockwriting e unlockwriting...all'interno del metodo run() del thread ogni client, prima di andare a modificare la variabile che tiene conto dei posti del locale, richiama il metodo lockwriting ponendo la variabile booleana writing a true inoltre se writing è già a true allora un thread va in wait...una volta modificata la variabile viene richiamato il metodo unlockwriting dove viene posta la writing a false e viene chiamato il notifyAll...in questo modo chi era in wait può andare ad occupare la risorsa...
nuovoUtente86
18-04-2008, 20:13
penso di non aver commesso errori nell'utilizzo wait() e notifyAll()...praticamente ho creato due nuovi metodi lockwriting e unlockwriting...all'interno del metodo run() del thread ogni client, prima di andare a modificare la variabile che tiene conto dei posti del locale, richiama il metodo lockwriting ponendo la variabile booleana writing a true inoltre se writing è già a true allora un thread va in wait...una volta modificata la variabile viene richiamato il metodo unlockwriting dove viene posta la writing a false e viene chiamato il notifyAll...in questo modo chi era in wait può andare ad occupare la risorsa...
è cosa cosa orrenda che non serve a nulla o meglio è un modo di simulare uno sincronizzazione che però gia fai con syncronized.
pumppkin
19-04-2008, 10:21
fai conto che anche i metodi lockwriting e unlockwriting sono synchronized...più che altro ho seguito una guida che ho trovato in rete...comunque tutto questo lo so che è abbastanza inutile, infatti avevo già scritto sopra che funzionava tutto anche con il solo synchronized, solo che per ora mi serve per esercitarmi o comunque capire in che modo posso fare la sincronizzazione tra i threads....
questa è la guida che, più o meno, ho seguito:
link (http://www.javastaff.com/article.php?story=20050928094924501)
nuovoUtente86
19-04-2008, 11:00
Come vedi l' esempio del link è quello classico dei lettori/scrittori dove l' utilizzo del wait() ha senso per consentire ai lettori di accedere contestualmente alla risorsa qualora nessuno la sta modificando.Nel tuo caso tutti i thread sono paritari.
Questo meccanismo ora è offerto dal linguaggio tramite la concretizzazione ReadWriteLock della superclasse Lock.
pumppkin
19-04-2008, 11:17
si ok hai ragione sul fatto che lì ha più senso...cmq come ti ho detto ho fatto solo una prova per vedere comunque se il programma girava senza problemi...adesso l'ho rimesso solo con il synchronized...cmq è strano che il prof non ha parlato della classe lock...ha parlato solo di wait notify, sleep, dei semafori, join...
nuovoUtente86
19-04-2008, 12:01
si ok hai ragione sul fatto che lì ha più senso...cmq come ti ho detto ho fatto solo una prova per vedere comunque se il programma girava senza problemi...adesso l'ho rimesso solo con il synchronized...cmq è strano che il prof non ha parlato della classe lock...ha parlato solo di wait notify, sleep, dei semafori, join...
Effettivamente è stano che vi abbia fatto fare solo la vecchia specifica.Di che corso si tratta?
pumppkin
19-04-2008, 14:45
è un corso sui sistemi distribuiti...tratta appunto la gestione e la progettazione di sistemi distribuiti..in particolare la realizzazione di un progetto distribuito in java...significa realizzare la connessione tramite socket, l'rmi e naturalmente gestire la sincronizzazione...
nuovoUtente86
19-04-2008, 16:03
è un corso sui sistemi distribuiti...tratta appunto la gestione e la progettazione di sistemi distribuiti..in particolare la realizzazione di un progetto distribuito in java...significa realizzare la connessione tramite socket, l'rmi e naturalmente gestire la sincronizzazione...
Al corso di distribuiti dovrebbe farsi la nuova specifica almeno che il tuo prof sia poco aggiornato o non so per quale assurdo motivo vi voglia fare realizzare il progetto con la versione 4 di java.
ziociccio07
21-04-2008, 09:07
neanche il mio prof di sistemi di elaborazione dell'università ha parlato mai della specifica lock(),ma solo di semafori,monitor (java e Hoare),ed altri monitor.
eppure è tra i migliori del mondo.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.