Newsgroup: it.comp.java
Titolo: thread e sincronizzazione

Salve a tutto il ng,
una mia applicazione è composta da due classi una che "scrive" dei file e
l'altra che li legge.
La prima è stata implementata in modo multithread e crea dei file
numerandoli progressivamente 0.txt, 1.txt, 2.txt, ecc. però non è detto che
la creazione dei file avvenga progressivamente e cioè nella maggiorparte dei
casi vi è la possibilità che il file 2.txt venga creato prima del file
0.txt.
La seconda classe non fa altro che aprire i file e leggerli in maniera
progressiva e cioè 0.txt, 1.txt, 2.txt ecc.
 Queste due classi sono richiamate da una terza che gestisce tutta
l'applicazione. Prima vengono create le istanze delle classi e poi
richiamati i metodi dell'una e poi dell'altra.
Molte volte la classe che legge inizia a lavorare prima che la classe che
scrive abbia finito per cui in questi casi va a leggere dei file che ancora
non sono stati creati e quindi lancia un'eccezione.
Conosco la possibilità di sincronizzare con synchronized ed ho letto
qualcosa sui monitor (wait e notify) ma non riesco ad applicarlo.
Qualche suggerimento?
alberto.

 non sono stati creati e quindi lancia un'eccezione.
Sei sicuro che si tratti proprio di un problema di sincronizzazione di
thread, e non in generale di logica dell'applicazione? P.es. potresti
mantenere un elenco di file pronti per l'elaborazione e scegliere il
prossimo da leggere tra quelli.

Il metodo per risolvere il tutto è proprio l'uso di synchronized. Cosa intendi
quando dici "non riesco ad applicarlo"?
lolito ha scritto:


 wrote in message
3A34DF48...@tin.it...


 siano terminati. E questo non me lo so spiegare.
Perché sincronizzi gli oggetti sbagliati. Penso che fai una cosa del genere:
class Lettore {
    synchronized void leggi() {
    .....
    }
}
class Scrittore {
    synchronized void scrivi() {
    .....
    }
}
Questo non serve a niente perché quando chiami il metodo scrivi() il lock
viene posto sull'oggetto Scrittore, mentre chiamando il metodo leggi() il
lock é preso sull'oggetto Lettore. Dunque niente impedisce a due thread di
chiamare contemporaneamente questi metodi.
Devi sincronizzare l'accesso a una risorsa, quindi é su qualcosa che
rappresenta la risorsa che devi mettere i lock. Un esempio:
class Risorsa {
    synchronized void leggi() {
    .....
    }
    synchronized void scrivi() {
    .....
    }
}
class Lettore {
    void leggi(Risorsa risorsa) {
        risorsa.leggi();
    }
}
class Scrittore {
    void scrivi(Risorsa risorsa) {
        risorsa.scrivi();
    }
}
La classe Risorsa rappresenta per esempio il file a cui devi accedere. Le
chiamate ai metodi leggi() o scrivi() di Risorsa sono sincronizzati sullo
stesso oggetto e dunque 2 thread non potranno accedere alla tua risorsa.
bye
Carlo


http://www.pabasoftware.com

 wrote in message
9131rf$jo9$1...@news.worldcom.ch...


 
certo! :)
Piu` o meno il discorso e` questo: in java ogni oggetto e` un "monitor",
una cosa cioe` in grado di gestire l'accesso ad una risorsa condivisa in
mutua esclusione. Tu puoi fare una cosa del tipo:
  class Pippo {
    void synchronized A() { /* .. */ }
    void synchronized B() { /* .. */ }
  }
e puoi essere sicuro che mai i metodi A e B di un'istanza "p" di "Pippo"
saranno eseguiti contemporaneamente. Infatti "p" fara` da monitor,
gestendo la concorrenza e tutto il resto.
Se invece fai -come mi sembra aver capito hai fatto tu-
  class Pluto {
    void synchronized A() { /* .. */ }
  }
  class Paperino {
    void synchronized B() { /* .. */ }
  }
non ottieni un bel niente! Perche` la sincronizzazione e` "rispetto al
monitor", che implicitamente e` l'istanza della classe ("this"). In
questo caso avresti invece due monitor, che si ignorano l'un l'altro e
quindi lasciano eseguire A() e B() concorrentemente.
E` cmq possibile sincronizzare porzioni di codice (non metodi) che
risiedono in classi diverse, e questo dichiarando dei blocchi
"syncronized" e indicando esplicitamente l'oggetto rispetto al quale ci
si sta` sincronizzando.
Per chiarirsi:
   class Lettore extends Thread {
      private File file;
      public Lettore( File f ) {
	file = f;
        // ottiene un Reader associato a file
        // per eseguire la lettura
        // ...
      }
      public void leggi {
        /* nel blocco di codice che segue, ci si sincronizza
         * sull'oggetto "file", che e` condiviso con lo Scrittore
         */
	synchonized( file ) {
           // esegui la lettura da "file"
        }
      }
      public void run() {
        while( true ) { leggi(); }
      }
   }
   class Scrittore extends Thread {
      private File file;
      public Scrittore( File f ) {
	file = f;
        // ottiene un Writer associato a file
        // per eseguire la scrittura
        // ...
      }
      public void scrivi {
        /* nel blocco di codice che segue, ci si sincronizza
         * sull'oggetto "file", che e` condiviso con il Lettore
         */
	synchonized( file ) {
           // esegui la scrittura su "file"
        }
      }
      public void run() {
        while( true ) { scrivi(); }
      }
   }
a questo punto se fai qualcosa del tipo:
   File f = new File( /*..*/ );
   new Scrittore( f ).start();
   new Lettore( f ).start();
credo che "piu` o meno" possa funzionare.
Ovvio che dovrai scrivere del codice migliore del mio xo`! ;-)
...insomma: questa e` l'idea. Spero di essere stato chiaro. Secondo me
-visto il problema da risolvere- e` piu` "pulita" questa di soluzione,
rispetto a quella che ti hanno gia` proposto di utilizzare una classe
di appoggio "risorsa" contenente i metodi utilizzati da Lettore e
Scrittore (che cosi` si ridurrebbero a semplice "wrapper" di risorsa),
e non e` piu` difficile da implementare.
Magari pensa meglio all'oggetto da utilizzare come monitor...
-- 
Ciao,  |  I play Russian roulette everyday, a man's sport,
Matteo |  With a bullet called life, yeah called life, (SUGAR)

 e non e` piu` difficile da implementare.
i nostri concetti di "pulizia", almeno per quanto riguarda la
programmazione, devono essere diversi....
Il fatto di poter definire dei blocchi synchronized all'interno di un metodo
é una facilità permessa in Java, ma secondo me poco elegante e poco object
oriented.
Sto parlando qui a livello di design. Nel fare il design di un'applicazione
la prima cosa da fare é ben ripartire le responsabilità tra le classi. Se
questo lavoro é ben fatto, aiutandosi anche con i design pattern, ecco che
l'applicazione é più flessibile, evolutiva, facile da mantenere.
Dunque quando piu' thread accedono ad una risorsa, chi deve avere la
responsabilità di impedire l'accesso simultaneo, le classi d'accesso o la
classe risorsa? Senza ombra di dubbio la risorsa. Perché? Perché é il suo
lavoro in quanto risorsa, mentre le classi d'accesso hanno come
responsabilità di effettuare un trattamento sulla risorsa.
Ma per venire a un esempio piu' pratico: immagina, come proponi tu, che
siano le classi d'accesso che si occupano della sincronizzazione, in
presenza di piu' threads che usano queste classi d'accesso. Ecco che in ogni
classe, in ogni metodo  che accede alla risorsa devi inserire un blocco
synchronized. Già questo non é bello. Poi immagina che un giorno crei una
nuova classe che accede alla risorsa ma dimentichi il blocco synchronized...
Se invece é la classe risorsa che si occupa di gestire correttamente gli
accessi, allora non c'é piu' bisogno di duplicare codice, ne pericolo di
dimenticanze. Un altro modo di fare non puo' che portare ad un garbuglio
totale e a perdere rapidamente il controllo del flusso d'esecuzione
nell'applicazione. Il multithreading é un soggetto molto difficile da
gestire quindi conviene adottare un metodo rigoroso e chiaro per gestirlo.
Questo metodo é importante cominciare ad applicarlo fin dai progetti piu'
piccoli, perché le cattive abitudini non si perdono per magia quando si
comincia a lavorare su progetti seri.
bye
Carlo

 comincia a lavorare su progetti seri.
Giusto! Praticamente era quello che volevo dire io prima :-)

 responsabilità di effettuare un trattamento sulla risorsa.
Il Design migliore è in effetti questo. E' un ottimo esempio di
incapsulamento. Il pattern applicato in questo caso (una "rule of thumb"
che può essere d'aiuto nel prendere decisioni di questo tipo) si chiama
"Expert Pattern", la cui sinossi è questa:
"Assegnare le responsabilità all'esperto, cioè a chi possiede le
informazioni necessarie per svolgere correttamente l'operazione"
Sembra banale, ma non lo è. Aggiungo anche il link alla relativa pagina
sul mio sito (il cui DNS non è ancora riattivato)
http://ugolandini.hypermart.net/ExpertPattern.html
 per chi volesse
approfondire/dare qualche consiglio.
ciao
-- 
Ugo
__________________________________________________________________________
"La perfezione si ottiene non quando non c'è nient'altro da aggiungere, 
 bensì quando non c'è più niente da togliere." Antoine de Saint-Exupéry
__________________________________________________________________________
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Enterprise Java Consulting
@mail:	
ugo.l...@flashnet.it
@work:	
ugo.l...@sun.com
Home Page: 
http://www.ugolandini.net
Home Page: 
http://ugolandini.hypermart.net
 (DNS is changing)
Fax Phone: 06/233207542 
Cell Phone: 0347/6310749 - 0347/4783580
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

 Carlo


 problema semplicissimo, probabilmente un esercizietto di fine capitolo.
e hai fatto bene, l'unica tua colpa é stata di parlare di maggior "pulizia"
di questa tecnica: mi ha fatto balzare dalla sedia ;-)
Comunque il mio scopo era di approfittare della cosa per introdurre nel
discorso le considerazioni di design object oriented che molto spesso sono
sconosciute ai programmatori alle prime armi (e troppo spesso trascurate da
quelli piu' sperimentati).
bye
Carlo


a proposito: qualche *buon* libro da consigliare con esempi "anche" in
Java? tutti i libri di cui ho notizia o non sono un granche`, o
contengono solo codice C++ (che x fortuna sto` iniziando a
dimenticare...)...


 dimenticare...)...
Conosco solo libri in inglese. Ti consiglio:
Peter Coad, Mark Mayfield, "Java design, building better apps & applets, 2e
edition", 1999, Yourdon Press
Presenta diverse strategie per fare il design di un'applicazione, insiste
sull'uso delle interfacce per un massimo di flessibilità  et "pluggabilità",
ha tutto un capitolo sul design robusto del multithreading. Peter Coad é il
grande capo del tool UML/Java TogetherJ. Meglio già avere una buona
comprensione delle problematiche OO.
Mark Grand, "Patterns in Java, Vol. 1", 1998, Wiley
Si tratta di un catalogo di design pattern, con esempi di codice in Java.
Molto interessante come referenza. Purtroppo la mia edizione contiene
diversi errori, ma sul sito dell'autore ci sono tutte le correzioni. Tra
poco dovrebbe uscire il volume 2.
Stephen Gilbert, Bill McCarty, "Object oriented design in Java", 1998, Waite
Group
Questo é un buon libro per i debuttanti perché inizia spiegando i fondamenti
di Java e della programmazione oggetto, per poi approfondire gli aspetti di
design. Spiega i vari esempi passo dopo passo ed é molto pedagogico. E'
veramente da consigliare ai debuttanti, ma non é adatto ai programmatori
esperti.
Se qualcuno conosce qualche altro libro da aggiungere a questa lista, sono
molto interessato.
bye
Carlo

 Carlo
-- 
Ciao,     |   And the devil in black dress watches over
 Matteo   |   My guardian angel walks away
          |   Life is short and love is always over in the morning
          |   Black wind come carry me far away

 
Il secondo volume è uscito da un pezzo ed è molto peggio del primo.


 Il secondo volume è uscito da un pezzo ed è molto peggio del primo.
In effetti é il terzo che deve ancora uscire.
Mi piacerebbe spiegassi in cosa trovi questo libro pessimo. Non l'ho letto
interamente perché l'ho piuttosto consultato per darmi delle idee di design
su dei bisogni miei ben precisi, ma a parte i molti errori tipografici non
mi é parso trovare castronerie.
bye
Carlo

 
a parte che troppi typo dovrebbero già far capire la cura che è stata
messa nella produzione del libro, semplicemente queli elencati non sono
design patterns, ma una serie di tips and tricks fra il banale ed il
meno. Può anche avere la sua utilità se sono cose che già non hai letto
da qualche altra parte, ma è molto meglio ad esempio la guida di Scott
Ambler sugli standard di codifica disponibile liberamente online:
comunque non è una collezione di Design Patterns che sono di solito
qualcosa di più sofisticato.
Il primo volume, meno "dispersivo", contiene invece del codice che non
illustra lo spirito dei Dp, ma è comunque utile (anche se potenzialmente
pericoloso) se non si riesce a leggere l'originale in C++.
E' opinione comune della comunità dei patterns che Grand abbia
approfittato delle buzzword dell'epoca per vendere qualche copia in più.
Un po' come se oggi mi venisse in mente di scrivere un libro come "XML
and UML together: exploit the power" oppure "xTreme Programming on the
Web: the bible"
ciao


 Web: the bible"
ROTFL!
Il bullshit detector e' impazzito! ;-))

Ciao,
ok, cosi' imparo a consigliare un libro senza averlo letto veramente.
Peccato perché il principio di avere un catalogo di pattern a cui ispirarsi
e consultabile rapidamente mi sembra buono.
Forse puoi consigliarmi un'altro testo del genere, ma di qualità?
PS: sto consultando il sito di Scott Ambler e mi sembra interessante: da
approfondire.
bye
Carlo

 
...scusa me alla fine non ho capito una cosa: se si esclude la classica
"bibbia" (leggi: GoF), c'e` un libro sui Pattern che ti senti di
consigliare o sono tutti da evitare? Ho dato un'occhiata alla sezione
libri del tuo sito: non e` che ci sia molta scelta...


 
A parte che la mia sezione libri è solo un parere personale e oltretutto
neanche ben aggiornato (ora ho un po' più di tempo libero e credo per il
2001 di ricominciare a scrivere e finire la sez. sui pattern - il 2000 è
stata proprio un'annataccia), penso proprio che ancora la scelta non ci
sia.
Leggere il GoF è indispensabile: gli altri libri possono anche essere
letti, io devo dire che ho trovato qualcosa di buono anche nel Grand. Il
problema del Grand (vol.1, il 2 è assolutamente OT) è che ha trascurato
tante piccole cose: il codice non funziona oppure è addirittura un
antipattern (c'è un esempio con una factory che utilizza una costante,
che è proprio una delle cose che si vorrebbe evitare), ci sono troppi
typo, non vengono utilizzate le interfacce come dovrebbero. I 23 pattern
GoF richiedono a mio parere uno studio approfondito e non superficiale,
ed un libro del genere può paradossalmente essere utile solo ad uno che
già li conosce e sa come evitare le trappole.
Anche del libro di Cooper "Java Design Patterns" ho sentito pareri
contrastanti, ma ancora non l'ho letto e più che riportare opinioni
altrui non so. Il libro di C.Larman è buono ma non così approfondito sui
Dp come gli altri.
Ecco, se accettate un consiglio, sforzatevi e continuate a leggere il
GoF, magari aiutandovi con le "traduzioni" in italiano e gli esempi sul
mio sito: anche qui però valgono gli stessi "rimproveri" fatti al Grand.
Il mio codice infatti funziona perfettamente essendo preso direttamente
dalla mia directory di progetti, però non è per niente detto che sia un
ottimo esempio o che sia il miglior modo di implementare il pattern in
questione, anche perchè ho ricevuto zero feedback sull'argomento e gli
esempi sono sempre stati scritti in pochi minuti (se avessi scritto un
libro come Grand probabilmente avrebbero bastonato e trovato da ridire
anche sui miei esempi!).
A questo punto si possono utilizzare gli esempi in Java sul mio sito (e
la traduzione più le mie note se non si conosce bene l'inglese) per
avere una buona approssimazione del pattern in questione, poi magari
cercare di sforzarsi a capire gli esempi del GoF in C++ e Smalltalk, poi
magari cercare ancora su Internet altri articoli ed altri esempi dello
stesso pattern: io ho sempre usato l'approccio forza bruta per venire a
capo di una cosa complicata, e mi sono letto e riletto di tutto su un
argomento per avere una idea più completa possibile.
Dopo tutto questo lungo discorso, mi viene in mente che si potrebbe
anche cominciare leggendo il libro di Fowler "Refactoring", eccellente,
in cui vengono applicati dei DP (ma NON è un libro sui dP) ad esempi di
codice che vengono "migliorati" con l'applicazione di trasformazioni. Si
potrebbe poi tornare al GoF forti di un approccio induttivo e pragmatico
che può aiutare a sgrossare un po' dell'aura mistica che c'è intorno
all'argomento.
Nonostante questo libro non spieghi i DP direttamente, potrebbe essere
un ottimo modo per cominciare oppure per approfondire il Design (dipende
quale dei due avete letto prima!), ed è di più semplice lettura (anche
se qualche volta da per scontata una certa conoscenza dei DP stessi)
perchè meno "teorico": il codice sta lì e si può guardare prima e dopo
l'applicazione delle tecniche di refactoring.


 mio sito
gia`, e da visitatore del sito posso dire: *grazie* per il supporto! :-)
