Newsgroup: it.comp.java
Titolo: PRIME ARMI: Problema con Synchronized. (lunghetto)

Ciao siamo al secondo giorno con lo studio dei thread ma abbiamo dei
problemi con il parametro synchronized
nel seg. codice. Spero possiate aiutarci.
class PingMain{
  public static void main(String args[]){
    Printer pt=new Printer();
    (new Ping(pt)).start();
    (new Pong(pt)).start();
  }
}
class Ping extends Thread{
  private Printer pt;
  public Ping(Printer pt){
 
this.pt
=pt;
  }
  public void run(){
    for(int i=1;i<=10;i++){
      pt.ping();
    }
  }
}
class Pong extends Thread{
  private Printer pt;
  public Pong(Printer pt){
 
this.pt
=pt;
  }
  public void run(){
    for(int i=1;i<=10;i++){
      pt.pong();
    }
  }
}
class Printer{
  private boolean eseguito=false;
  public void ping(){
    synchronized(getClass()){  --------------->PROBLEMA
       if(eseguito)
        try{
          wait();
        }catch(Exception err){}
      System.out.println("Ping");
      eseguito=true;
      notify();
    }
  }
  public void pong(){
    synchronized(getClass()){---------------->PROBLEMA
     if(!eseguito)
        try{
          wait();
        }catch(Exception err){}
      System.out.println("Pong");
      eseguito=false;
      notify();
     }
  }
}
Usando synchronized nel modo seg. otteniamo il seg. errore di runtime:
Ping
java.lang.IllegalMonitorStateException: current thread not owner
        at java.lang.Object.notify(Native Method)
        at Printer.ping(Printer.java:12)
        at Ping.run(Ping.java:8)
Pong
java.lang.IllegalMonitorStateException: current thread not owner
        at java.lang.Object.notify(Native Method)
        at Printer.pong(Printer.java:23)
        at Pong.run(Pong.java:8)
Se invece impostiamo synchronized per tutto il metodo, cioè prima del void,
allora tutto va bene.
Che può essere? Forse che il codice in questov caso cerca di mettere in wait
un thread che è già in wait
o di richiamare con notify un thread già attivo?
Non ho idea.
Grazie.

     synchronized(getClass()){  --------------->PROBLEMA
Forse volevi scrivere
   public void ping(){
     synchronized(this) {
     ...
     }
   }
che nel tuo caso sarebbe praticamente equivalente 
a scrivere
   public synchronized void ping() 
   {
      ...
   }
Ciao
Roberto
-- 
+-------------------+
| Bagnoli Roberto   |
| Nouvelle srl      |
| MODENA (ITALY)    |
| 
rbag...@orion.it
 |
+-------------------+

    }
Mmmm...no, veramente volevamo scrivere proprio cosě....
E ci da errore....e non sappiamo perchč....

     }
La sincronizzazione si effettua sempre relativamente a un oggetto preciso.
Se metti l'oggetto A in accesso esclusivo con synchronized, le operazioni
wait() e notify() devi eseguirle per rapporto a questo stesso oggetto A (ex:
A.wait() e A.notify()). Quando sincronizzi un metodo in realtà stai
sincronizzando this, e wait() e notify() sono equivalenti a this.wait() e
this.notify().
L'eccezione IllegalMonitorState é sollevata nel tuo codice perché dopo aver
sincronizzato un'istanza di Class, chami wait() e notify() sull'istanza
this, ma this non essendo sincronizzato le operazioni sono illegali.
Nel tuo caso devi quindi fare qualcosa come:
public void ping(){
    Class class = getClass();
    synchronized(class) {
        if(eseguito)
             try{
                 class.wait();
             } catch(Exception err){}
       System.out.println("Ping");
       eseguito=true;
       class.notify();
    }
}
Una domanda. L'utilizzo di getClass() non mi sembra avere molto senso in
questo contesto. Puoi spiegare il tuo ragionamento?
bye
Carlo

 ha scritto nel messaggio
news:3c8746b3$1...@news.bluewin.ch...

Grazie per la spiegazione.
getClass mi restituisce il nome dell'oggetto chiamante, cioè del thread
chiamante.
Cmq questo è il codice che ci ha fatto fare il professore ^_^
Ciao.

Cmq questo č il codice che ci ha fatto fare il professore ^_^
Ammesso che il codice sia _proprio_questo_, č un modo quantomeno 
bizzarro.
Ti consiglio di leggere le parti relative alla sincronizzazione sul 
Tutorial e su "Thinking in Java".
Oppure chiedi maggiori spiegazioni al tuo professore (e poi faccele 
sapere ;-).
HTH
-- 
Ciao
	Fabrizio C.

 Cmq questo è il codice che ci ha fatto fare il professore ^_^
getClass() restituisce un'istanza della classe dell'oggetto (in Java le
classi sono pure oggetti, di tipo Class). Un oggetto, di per sé, non ha un
nome.
Nel tuo esempio getClass() ritorna una referenza verso un'oggetto che
rappresenta la classe Printer caricata nella JVM.
Nel contesto del tuo esempio inoltre é inutile sincronizzare la classe. Per
sincronizzare l'accesso alle operazioni di Printer é sufficiente, e più
efficace, semplicemente sincronizzare i metodi ping() e pong().
Sincronizzare la classe di un'oggetto puo' eventualmente essere utile se hai
molti threads, tutti appartenenti alla stessa classe, e vuoi che lavorino in
accesso esclusivo fra loro. La classe, che hanno in comune, puo' servire da
semaforo.
Ma é un brutto design. Se dei thread devono lavorare in accesso esclusivo
significa che esiste una risorsa comune da proteggere da accessi
contemporanei (come il tuo oggetto Printer). Allora conviene creare una
classe che rappresenti questa risorsa e fare giocare a lei il ruolo di
semaforo.
bye
Carlo