Newsgroup: it.comp.java
Titolo: quesito sui lock

Salve a tutti.
Mi trovo nella seguente situazione :
 - C'è una classe A che contiene il metodo a.
 - E' istanziato un solo oggetto di tipo A;
 - Ci sono poi alcuni thread che chiamano concorrentemente il metodo a
di questo oggetto di tipo A.
C'è modo di gestire correttamente la concorrenza senza dichiarare
synchronized a () ?
Da quello che ho capito, synchronized a () tiene il lock per tutta
l'esecuzione di a.
Vorrei invece controllo a grana più sottile, che ottenga il lock solo
per alcune righe.
Ho provato a chiedere il lock per le righe del metodo a che lo
richiedono, ma non funziona.
Vorrei anche evitare di inserire il codice di a all'interno della
classe che implementa il Thread (anche se così funziona).
Mi sapreste aiutare?
Grazie

 writes:
BS> Ho provato a chiedere
BS> il lock per le righe del metodo a che lo richiedono, ma non
BS> funziona.
Come hai fatto ?
-- 
 /\           ___
/___/\_|_|\_|__|___Gian Uberto Lauri_____
  //--\| | \|  |   Integralista GNUslamico
\/                 e coltivatore diretto di Software

 per alcune righe.
void a()
{
    //non sincronizzato
    synchronized(this)
    {
        //blocco sincronizzato
    }
}

> che ottenga il lock solo per alcune righe.
e> void a()
e> {
e>     //non sincronizzato
e>     synchronized(this)
e>     {
e>         //blocco sincronizzato
e>     }
e> }
Hmmmm che sappia io in questo modo metti sempre un blocco sul this, cosa che
potrebbe non essere utile.
Io usualmente uso un'istanza di Object creata apposta allo scopo.


 
Esatto qualcosa tipo
final Object lock = new Object();
void a() {
   synchronized(lock) {
     // ...
   }
}


Con questo metodo funziona.
Però non riesco a spiegarmi perchè se chiedo il lock su un Object
creato allo scopo o su this funziona, mentre se lo chiedo sulla
variabile interessata (di tipo Integer) no.

 Io usualmente uso un'istanza di Object creata apposta allo scopo.
Mah, io sono daccordo fino ad un certo punto.
Ha senso se nell'oggetto hai bisogno di creare blocchi di codice
sincronizzati con lock diversi. Altrimenti se usi lo stesso lock non
cambia nulla fra sincronizzare 'this' o un'altro oggetto apposito.

> di Object creata apposta allo scopo.
e> Mah, io sono daccordo fino ad un certo punto.  Ha senso se
e> nell'oggetto hai bisogno di creare blocchi di codice sincronizzati
e> con lock diversi. Altrimenti se usi lo stesso lock non cambia nulla
e> fra sincronizzare 'this' o un'altro oggetto apposito.
Qualcosa cambia.  Tu fai il lock  su un oggetto nel  suo complesso. Se
fai il  lock sul this, lo stato  di quella istanza è  "sotto lock" che
potrebbe NON essere quello che desideri.
A  me  viene  in mente  un  membro  che  non  si è  potuto  dichiarare
final...  Dovrei rivedermi  la semantica  del  lock, ma  temo che  sia
bloccato anche il lettura...


 bloccato anche il lettura...
No, i lock non funzionano in questo modo.
quando tu richiedi il lock di un oggetto, quello che avviene è
qualsiasi altra richiesta di lock esclusivo dello stesso oggetto si
"accoda" in attesa che venga rilasciato (all'uscita del blocco
synchronized). Questo è tutto ciò che avviene.
Non c'è alcun "blocco" di accesso ai membri dell'oggetto, ne in
lettura e ne in scrittura.
Quello che io stavo dicendo è che se vuoi usare un semaforo diverso da
this puoi farlo, ma ricorda che:
- i metodi non statici synchronized richiedono implicitamente il lock
a this, quindi non si accodano al tuo semaforo
- chiunque da fuori vuole richiedere un lock esclusivo di 'oggetto'
con synchronized(oggetto) non si accoda al tuo semaforo
- se tu invece di this usi un semaforo all'interno dello stesso
oggetto l'effetto non cambia, crei comunque una coda
Come ho già detto può essere indiscutibilmente utile se vuoi creare
diversi semafori con diverse code. Ma in generale è buona norma
applicare i lock all'oggetto che si intende modificare.

 writes:
e> - i metodi non statici synchronized richiedono
e> implicitamente il lock a this, quindi non si accodano al tuo
e> semaforo
Era esattamente quello il motivo per cui lo usavo...
e> Come ho gią detto puņ essere indiscutibilmente utile se vuoi creare
e> diversi semafori con diverse code. Ma in generale č buona norma
e> applicare i lock all'oggetto che si intende modificare.
Fai un po' di confusione. Un oggetto che il cui accesso deve prevedere
politiche di sincronizzazione deve essere protetto sempre dal medesimo
semaforo.


 semaforo.
Io faccio confusione? :-)

> dal medesimo semaforo.
(s/semaforo/meccanismo/ non è detto che sia un semaforo, o un semaforo
 solo. Ciò non toglie che il meccanismo deve essere sempre il medesimo
 per un dato oggetto.)


 variabile interessata (di tipo Integer) no.
Uh, questo e' strano ! Magari c'entra qualcosa il fatto che Integer e' 
immutable ?

 immutable ?
Immagino proprio di si.

 Immagino proprio di si.
Ora mi devi spiegare perche' ;) !