Newsgroup: it.comp.java
Titolo: Incertezze sulla concorrenza

Ciao ha tutti
sto realizzando per l'università come progetto d'esame un supermercato
elettronico
Dovendo effettuare accesso ai database ( lettura e scrittura) devo occuparmi
della sincronizzazione delle
operazioni, onde evitare effetti indesiderati
Ho un lapsus sull'utilizzo del synchronized;
so che definendo metodi  static synchrnized in una classe, una istanza della
stessa classe non potrà
mai invocare lo stesso  metodo se questo è gia in esecuzione in un'altra
istanza;
il mio problema è :
Può invocare un altro metodo, definito anch'esso static synchronized,
contemporanemente a quello già in esecuzione (static sync ma diverso)?
E un metodo non sync ( ma static, ad esempio, o sulla stessa istanza)?

Può invocare un altro metodo
Questa sta diventando una FAQ. La riposta e' che si', puo' invocarlo, ma 
l'invocazione e' messa in coda.
Dichiarare 
 public synchronized pippo(...) {
   ..blablablah..
 }
equivale a
  public pippo(...) {
    	synchronized(this) {
    	   ..blablablah..
    	}
 }
Se non vuoi quest'effetto, basta usare oggetti
nei due metodi come lock. Qualcuno ha postato un esempio
qualche giorno fa, cerca con 
google.groups.com
.
-- 
Life's something u don't get out alive..
ObjectZone - 
http://space.tin.it/computer/csadun

...basta usare oggetti...
Mi e' scappato un "diversi" :-)


 ha scritto:

Ciao,
vista l'ora tarda e la stanchezza spero di non dire troppe sciocchezze...
synchronized serve per regolare l'accesso concorrente a dati sensibili (cioe' di cui
si deve garantire la consistenza) da parte di piu' thread che cercano di
utilizzarli/manipolarli "contemporaneamente".
Quindi non si deve pensare all'utilizzo di metodi synchronized da parte
di istanze di classi (il fatto che siano istanze della stessa classe e'
irrilevante), quanto piuttosto all'utilizzo di metodi syncronized da
parte di thread diversi.
In particolare, se un thread (A) sta eseguendo un metodo static synchronized
di una classe, nessun altro thread (B) potra' eseguire alcun metodo
static synchronized di quella classe. Se il thread B esegue una chiamata
ad un metodo static syncronized, esso verra' messo nel pool di attesa del
lock su quella classe, da cui potra' uscire solo quando il thread A
rilascera' quel flag di lock (cioe' uscira' dal metodo static
synchronized).
Viceversa il thread A potra' chiamare altri metodi static synchronized di
quella classe, dal momento che il flag di lock di quella classe lo ha
gia' acquisito (ed e' quindi l'unico thread che in quel momento e'
autorizzato ad eseguire tali metodi).
...se mi e' sfuggito qualcosa, vi prego perdonatemi e correggetemi.
Un saluto
  Lucio
-- 
Lucio Benfante
Brainbench MVP For Java 1
http://www.brainbench.com

 
Nello spazio di pensiero chiamato : it.comp.java 
Ha scritto questo messaggio : 

Ti hanno gia' risposto correttamente, ma non so' se hanno dissolto i
tuoi dubbi, nell'incertezza, ci provo anch'io. Molto schematicamente :
- Ogni oggetto (istanza di una classe) possiede un lock acquisibile da
un thread entrando in un blocco "synchronized"
- Ogni classe possiede un lock acquisibile da un thread entrando in un
blocco "static synchronized"
- I due lock sono diversi!
Quando un thread tenta di entrare in un blocco "synchronized" (static
o meno) :
- Se non possiede nessun lock, richiede il lock necessario per entrare
in quel blocco, se il lock e' gia' in possesso di qualcuno, si mette
nel pool di attesa, aspettando il suo turno. Altrimenti prende il lock
e prosegue
- Se possiede gia' un lock, ma e' diverso dal lock richiesto dal
blocco nel quale deve entrare, come sopra
- Se possiede gia' il lock necessario per entrare nel blocco, entra
semplicemente.
Tipi di blocchi synchronized :
- "synchronized{...}", che implicitamente e'
"synchronized(this){...}", richiede per essere eseguito il lock
dell'oggetto this
- "synchronized(refObj)", richiede per essere eseguito il lock
dell'oggetto refObj
- "static synchronized", richiede per essere eseduito il lock della
classe nella quale e' dichiarato il blocco (che ovviamente e' comune a
tutte le istanze di quella classe!)
Quando un thread esce da un blocco "synchronized", restituisce il lock
che aveva acquisito al suo ingresso
Se ci sono ancora dei dubbi, non esitare a chiedere
[}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{]
SunGray aka Gabriele Lana  
www.redangel.it
www.sungray.com
contact me @ : 
www.redangel.it
contact me @ : 
sun...@tiscalinet.it
[}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{]


Ti hanno già spiegato tutto, ma provo a dire la mia lo stesso perchè
penso che l'argomento può essere un po' semplificato costruendoti un
modello del "come".
Prendi il punto di vista dell'oggetto: ogni oggetto ha un lock (monitor,
testimone, pallina, chiamalo come vuoi). Se lo ritrova perchè il lock è
definito su nella gerarchia fin da Object (la madre di tutte le classi,
che lo si espliciti o no).
I metodi synchronized, rispetto a quelli non synchronized, hanno
semplicemente la caratteristica di dover "prendere" il lock dell'oggetto
in cui sono definiti prima di essere eseguiti, altrimenti devono
attenderlo.
Visto che il lock è per oggetto e non per metodo, appare chiaro che due
metodi sync dello stesso oggetto (non classe, bada bene) non possono
essere eseguiti contemporaneamente, come d'altronde lo stesso metodo
sync sullo stesso oggetto non può essere eseguito contemporaneamente
(semplicemente perchè il metodo sync deve attendere il lock, stesso caso
di prima).
Soprattutto il primo caso spesso non è chiaro: due DIFFERENTI metodi
sync non possono essere eseguiti contemporaneamente sullo stesso
oggetto. Spesso molti credono che il synchronized sia sul metodo, ossia
che ci sia una sorta di lock per ogni metodo, scrivendo così del codice
terribile. Ed invece tutti i metodi synchronized competono per la stessa
risorsa, ossia il lock dell'oggetto. E' anche chiaro che due diversi
oggetti hanno due lock diversi, quindi i loro metodi synchronized
possono essere eseguiti contemporaneamente, a prescindere dal lock.
Ma se il lock è sull'oggetto, ossai su una spocifica istanza, che fanno
i metodi static synchronized? (un metodo static non ha il this
implicito, può essere invocato anche senza una istanza ben specifica
della classe, ossia Class.method())
Semplicemente utilizzano il lock dell'oggetto di classe Class (una
classe utilizzata ad esempio per la Reflection) del tipo che
rappresentano. Quindi il meccanismo è identico a prima, salvo che il
lock è in qualche modo sull'oggetto di Classe e non sulle istanze.
Chiaramente, essendo i lock diversi, i metodi static synchro e synchro
non si influenzano assolutamente l'un l'altro.
Ultima cosa, la keyword synchronized può essere usata in un blocco e non
nella signature del metodo. In questo modo puoi minimizzare l'ampiezza
("scope") del blocco di codice che vuoi sincronizzare (ade sempio per
ottimizzare le performance), e soprattutto esplicitare di quale oggetto
vuoi acquisire il lock (potrebbe essere un altro e non quello su cui
stai invocando i metodi).
spero di esserti stato di qualche aiuto
ciao!
uL

 uL
Ultimissima cosa: se all'interno di un metodo sync chiamo un altro sync
cosa succede? Si potrebbe infatti pensare che il metodo si "incanti", in
quanto il metodo dovrebbe attendere un lock che non arriverà mai, in
quanto è lui stesso a possederlo. In realtà, chiaramente, il metodo
semplicemente, essendo in possesso del lock, non ha bisogno di
riottenerlo ed il tutto funzionerà... ossia il metodo non rilascerà il
lock che già aveva e continuerà a detenerlo fino all'uscita dall'ultimo
metodo sync.
ciao
uL