|
|
|
![]() |
|
Strumenti |
![]() |
#21 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Tieni conto che l'EDT potrebbe già essere in esecuzione. Diverso sarebbe se l'EDT non lo fosse.
In generale se un Thread A avvia un Thread B - cioè causa l'invocazione del metodo start di quel Thread B - allora ciò che ha fatto il Thread A prima di avviare B è visibile in B - perchè secondo il modello di memoria le azioni compiute da un thread prima dell'avvio di un secondo thread "happens-before" la prima istruzione eseguita dal Thread avviato. Ma se B è già in esecuzione non c'è la condizione happens-before. Da notare che i vincoli "happens-before" imponendo che alcuni effetti debbano essere necessariamente visibili tra Thread diversi dicono anche che non è possibile che una certa implementazione di Java causi il riordino delle istruzioni. E' paradossale ma così: Codice:
public void metodo() { EventQueue.invokeLater(new Runnable() { public void run() {}}); }
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#22 | ||
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
Ho letto bene l'esempio dell'algoritmo, e l'ho capito in larga misura anche se mi perdonerai l'ignoranza dei meccanismi degli oggetti Lock e Condition, che non ho mai ne studiato ne usato (appena ho tempo vado a scovarli nella javadoc). Quote:
Codice:
final Point point = new Point(); final Lock lock = new ReentrantLock(); final Condition stop = lock.newCondition(); boolean reading, closing; public void set(int x, int y) throws InterruptedException { lock.lock(); try { while(reading && !closing) { stop.await(); } if (closing) { // se sto chiudendo l'applicazione posso anche // infischiarmene del tentativo di mutazione di stato // di 'point' da parte del thread corrente stop.signalAll(); } else { point.x = x; point.y = y; reading = true; EventQueue.invokeLater(new Runnable() { public void run() { read(); } }); } } finally { lock.unlock(); } } private void read() { lock.lock(); try { int x = point.x; int y = point.y; appendText("Letto (" + x + "," + y + ")"); reading = false; stop.signalAll(); } finally { lock.unlock(); } } public void notifyClosing() { closing = true; } ![]()
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) Ultima modifica di banryu79 : 14-07-2009 alle 15:22. |
||
![]() |
![]() |
![]() |
#23 | |
Senior Member
Iscritto dal: Feb 2007
Città: Verona
Messaggi: 1060
|
Quote:
Se così fosse, allora non c'ho capito niente. Com'è possibile che run venga richiamato dall'EDT, prima di avergli passato l'oggetto Runnable su cui verrà richiamato proprio il run() ? Scusa se ti rompo, è che proprio non riesco a capire questa logica... ![]() E se invece con metodo intendi l'intero blocco di codice in metodo(), allora siamo d'accordo; non c'è nessuna certezza riguardo all'ordine di esecuzione del codice che viene DOPO la chiamata di InvokeLater, in quanto il thread che sta eseguendo metodo() potrebbe uscire dallo stato di running, ma secondo me il codice che viene PRIMA dell'InvokeLater è certo di essere eseguito prima del codice contenuto nel run(). ![]() In ogni caso, grazie della tua pazienza ![]()
__________________
|
|
![]() |
![]() |
![]() |
#24 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
C'è un problema con closing perchè l'accesso in scrittura (in notifyClosing) non è sincronizzato con l'accesso in lettura (in set). Ciò significa che un Thread è libero di "non vedere" la mutazione di closing a true che un altro Thread applichi invocando notifyClosing.
Dopodichè dobbiamo metterci nell'ottica "cosa succede se". E quest'ottica ci dice che il codice che io ho incollato ha un bug. Cosa succede se l'EDT muore dopo aver eseguito "appendText" e prima di aver eseguito "reading = false"? Succede che il programma va in stallo perchè reading resta false ed eventuali altri Thread in attesa per eseguire set() non saranno mai risvegliati. Se morisse dopo non sarebbe un problema perchè il successivo invocante di set lo riattiverebbe. Bisognerebbe spostare il reading = false nel finally E circondare EventQueue.invokeLater con un try-catch(Throwable) { reading = false; }. A conti fatti la soluzione che creava più punti teneva la porta chiusa ad un sacco di problemi. Salva quasta chicca che è un problema creato da me il tuo codice è ok. Nota però come notifyClosing sia solo una richiesta di spegnimento e non uno spegnimento immediato. Funziona solo dopo che l'edt ha eseguito stop.notifyAll(): a quel punto i thread risvegliati incontreranno un while in cui reading vale true e (!closing) false quindi salteranno direttamente al finally. Pensa adesso a quanto sarebbe "divertente" se il meccanismo che volessimo adottare non fosse semplice un "ferma tutto" ma un "avvia-metti in pausa-ferma-riavvia".
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#25 | |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Quote:
Codice:
public void metodo() { System.out.println("ciao"); EventQueue.invokeLater(new Runnable() { public void run() { System.out.println("mondo"); } }); } "ciao" "mondo" ma anche: "mondo" "ciao" E' la ragione per cui le variabile locali accedute da una classe locale devono essere dichiarate final: obbliga la piattaforma a dare un valore alla variabile prima che quella variabile sia usata nella classe locale. Senza il final l'uso della variabile nella classe locale potrebbe avvenire prima della sua inizializzazione.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
|
![]() |
![]() |
![]() |
#26 | |
Senior Member
Iscritto dal: Feb 2007
Città: Verona
Messaggi: 1060
|
Quote:
Non avresti qualche link interessante sull'argomento?
__________________
|
|
![]() |
![]() |
![]() |
#27 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
![]() Qui c'è un sito dedicato a risorse in merito al modello di memoria: http://www.cs.umd.edu/~pugh/java/memoryModel/
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#28 | ||||
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
Codice:
final Point point = new Point(); final Lock lock = new ReentrantLock(); final Condition stop = lock.newCondition(); boolean reading, closing; public void set(int x, int y) throws InterruptedException { lock.lock(); try { while(reading && !closing) { stop.await(); } if (closing) { stop.signalAll(); } else { point.x = x; point.y = y; reading = true; try { EventQueue.invokeLater(new Runnable() { public void run() { read(); } }); } catch (Throwable t) { // EDT e' morto reading = false; } } } finally { lock.unlock(); } } private void read() { lock.lock(); try { int x = point.x; int y = point.y; appendText("Letto (" + x + "," + y + ")"); stop.signalAll(); } finally { reading = false; lock.unlock(); } } public void notifyClosing() { closing = true; } Quote:
Quote:
Quote:
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) Ultima modifica di banryu79 : 14-07-2009 alle 16:33. |
||||
![]() |
![]() |
![]() |
#29 |
Senior Member
Iscritto dal: Oct 2006
Città: milano
Messaggi: 1439
|
Quando Chuck Norris programma in Java, non cerca nella documentazione per risolvere i problemi, chiede aiuto a PGI-bis
![]() |
![]() |
![]() |
![]() |
#30 | |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Quote:
Quando c'è qualcuno nella stanza la porta è chiusa e la chiave non è sul tavolino quindi tutti quelli che vogliono entrare devono aspettare che chi è dentro esca e rimetta a disposizione la chiave. La condizione che derivi da un Lock funziona come un buttafuori. Ci sono n Thread che vogliono entrare. Uno prende la chiave, apre la porta e se una certa condizione è vera il buttafuori gli frega la chiave, gli mena un cazzotto in faccia che lo fa volare in anticamera lungo disteso, chiude la porta da dentro e butta fuori la chiave passandola sotto la porta. Finchè il valore di controllo causa l'invocazione di condition.await() chi entra si becca il cazzotto del dolce dormire. L'invocazione condition.signalAll() è un messaggio al buttafuori di quella porta: piglia e versa una secchiata d'acqua sui poveri disgraziati che hai addormentato a cazzotti. Quelli si svegliano e si trovano di nuovo davanti alla porta chiusa. Uno prende la chiave, entra, verifica la condizione buttafuori... eccetera eccetera. Da notare che il fatto di aver preso un pugno in faccia non rende i thread risvegliati prioritari rispetto a qualche altro Thread sopraggiunto nel frattempo davanti alla stessa porta: il classico cornuto e mazziato - con la variante della mazziata preventiva.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
|
![]() |
![]() |
![]() |
#31 | |
Senior Member
Iscritto dal: Feb 2007
Città: Verona
Messaggi: 1060
|
Quote:
![]()
__________________
|
|
![]() |
![]() |
![]() |
#32 | |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
![]() Tra l'altro sto esaminando la documentazione del package java.util.concurrent.lock e appena imbattutomi nella descrizione sommaria di Lock e Condition ho capito che mi mancava un pezzo. Potevo lasciare la prima implementazione che avevo scritto ma poi editato, quella cioè che semplicemente controlava nell'if se closing era falsa e quindi procedeva con il setting dei campi del punto e l'accodamento della lettura da far eseguire a EDT. Thank you ![]() EDIT: Certo che un tutorial sulla concorrenza in versione "goliardica" sarebbe una chicca, anche perchè oltre ad una comprensione completa, ci vuole una capacità più unica che rara per spiegare un argomento così tecnico mediante metafore divertenti ![]()
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) Ultima modifica di banryu79 : 14-07-2009 alle 17:26. |
|
![]() |
![]() |
![]() |
#33 | |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
Ma immagino che se nella nostra implementazione avessimo bisogno di stare pure a riconoscere a ogni singolo thread il suo diritto di prelazione, in virtù del tempo di attesa, rispetto gli altri suoi compagni (magari dobbiamo assicurare che l'accesso sia concesso rispettando l'ordine di invocazione del metodo da parte dei thread), il che corrisponderebbe ad accodare in ordine il punto modificato nella coda dell'EDT, dovremmo inventarci qualcosa di terribilmente contorto ![]() Tipo un meccanismo che, ad ogni tentativo di acquisizione del lock che non va a buon fine, a causa della condizione derivata sul lock[condition.wait], prende il thread corrente, e lo infila in una coda. Poi però andrebbe gestito il momento in cui è di nuovo possibile per i thread lockare [condition.signalAll]; bisognerebbe in qualche modo garantire che i tentativi di locking della risorsa da parte dei thread nella coda avvenissero rispettando l'ordine FIFO dei thread nella coda, senza contare dei "nuovi" thread che potrebbero arrivare nel frattempo, ignari di tutto questo bailamme... Ma forse sto vaneggiando, e non si fa così ![]()
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) Ultima modifica di banryu79 : 14-07-2009 alle 17:55. |
|
![]() |
![]() |
![]() |
#34 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Non è una necessità peregrina. Se pensi ad un web server e alle richieste che deve gestire in concorso è normale pensare al fatto che debba esistere un qualche politica di correttezza riguardante l'accesso al servizio altrimenti io potrei aspettare cent'anni di avere una pagina web perchè li server mi fa passare davanti tutte le altre richieste che arrivano.
Nel package concurrent si può usare Semaphore che ha un'opzione fairness verificata la quale il metodo acquire() garantisce - poco evangelicamente - che i primi saranno i primi.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#35 | |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
Javadoc del package e link sul memory model a parte, conosci qualche risorsa paragonabile ai tutorial del Really Big Index (per dare un'idea) che tratti dei meccanismi per la gestione della concorrenza in Java, al di la di quelli implementati direttamente nel linguaggio?
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
![]() |
![]() |
![]() |
#36 |
Bannato
Iscritto dal: Jul 2009
Messaggi: 6
|
"Posterizza, analizza e rasterizza".. Così diceva il mio prof... Prova...
|
![]() |
![]() |
![]() |
#37 | |
Senior Member
Iscritto dal: Feb 2007
Città: Verona
Messaggi: 1060
|
Quote:
@pgi: mi sto leggendo con calma il documento linkato, sto così: ![]() ![]()
__________________
|
|
![]() |
![]() |
![]() |
#38 | ||
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
Ho trovato utile anche questo link: http://www.ibm.com/developerworks/ja...j-jtp0618.html Se non ho capito male (cerco conferma da chi può darla) il "nuovo" memory model è arrivato con la versione 5 di Java, pertanto è impementato dalle JVM di versione 1.5 o superiori, corretto? Inoltre ho una domanda per PGI, in riferimento allo spezzone di codice precedente, su cui abbiamo ragionato. Quote:
Grazie ![]()
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) Ultima modifica di banryu79 : 16-07-2009 alle 11:04. |
||
![]() |
![]() |
![]() |
#39 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Sì puoi usare anche volatile - o AtomicBoolean.
Non so se il nuovo memory model sia valido solo a partire da Java 1.5. In teoria è una migliore specificazione di qualcosa che avrebbe dovuto già esistere ma se è stata necessaria significa che qualcosa che non andava nei precedenti JRE c'era.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#40 | |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
![]() Mah, siccome in parte rigurda anche ciò che il compilatore e la virtual machine possono e non possono fare [per esempio la faccenda del riordino di letture e scritture tra variabili volatile e variabili "normali"] e anche le specifiche per la JVM suppongo che uno la garanzia di lavorare con il nuovo memory model ce l'ha solo da una certa versione della piattaforma in poi. Prima ti chiedevo se conosci una risorsa a mo' di tutorial sull'uso delle classi del package java.util.concurrent, da affiancare alla javadoc per motivi di studio.
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) Ultima modifica di banryu79 : 16-07-2009 alle 17:22. |
|
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 21:20.