Newsgroup: it.comp.java
Titolo: Comportamento sospettoso.

Premetto che uso JDK 1.1.8_008 per Win(DOS) e non sono molto esperto di
programmazione Java.
Nello scrivere un programmino che doveva andare appositamente in
deadlock ho scoperto un comportamento completamente anomalo rispetto al
codice scritto: che sia un bug della V.M. ?
Qui sotto riporto il codice, che dovrebbe fare le seguenti cose:
-istanziare due classi di tipo "ista" contenenti una funzione di tipo
"syncronized" ed una normale. La prima funzione (syncronized) chiama la
seconda (normale) dell'altra istanza in modo reciproco per le due
istanze.
-istanziare due thread sotto forma di oggetti "deadl" (derivati appunto
dalla classe Thread) ognuno dei quali possiede (per costruzione) la
reference di una delle due istanze precedentemente create e ne chiama il
metodo sincronizzato.
Il metodo sincronizzato della classe "ista" attende 2 secondi
utilizzando la sleep() dell'oggetto "dead" che la chiama.
Sembra che, anziche' creare due oggetti "deadl" (quindi Thread)
distinti, la V.M. ne crei due uguali passando al costruttore gli stessi
parametri. Piu' precisamente uguali al secondo che viene richiesto di
istanziare.
So che la prova costa un po di tempo ma questo potrebbe essere un BUG
bello e buono: si provi a commentare una delle due richieste di
istanziazione ed avvio dei thread e si vedra' che il S.W. funziona
perfettamente. Se ne vengono richiesti due, invece, essi saranno
identici indipendentemente dai parametri passati al costruttore del
primo, e questo e' un errore!
Riporto qui sotto il codice da copiare (senza nient'altro) in un file di
testo chiamato deadl.java che dovra' essere compilato con javac senza
nessun parametro.
----------------------------------------------------------------------------------------------------------------
import java.lang.*;
public class deadl extends Thread
{
static ista fantoc1,fantoc2;
static String nome;
deadl(ista fantoc1, ista fantoc2, String nome)
	{
	this.fantoc1=fantoc1;
	this.fantoc2=fantoc2;
	this.nome=nome;
	}
public static void main(String args[])
	{
	deadl child1, child2;
	fantoc2 = new ista((String)"bicicletta");
	fantoc1 = new ista((String)"macchina");
	child1 = new deadl(fantoc1,fantoc2,"Pippo");
	child2 = new deadl(fantoc2,fantoc1,"Topolino");
	child1.start();
	child2.start();
	}
public void run()
	{
	System.out.println(nome+": ora chiamero' : "+fantoc1.nome+"-> a(-)\n");
	fantoc1.a(this,fantoc2);
	}
}
class ista
{
String nome;
ista(String nome)
	{
	this.nome = nome;
	}
synchronized void a(deadl serve, ista usa)
	{
	System.out.println(serve.nome+"-> Sono in: "+nome+"\n");
	try {
		serve.sleep(2000);
		}
	catch (Exception e) {
		System.out.println("Ho perso il timer(:-( \n");
		}
	usa.b(nome+": sto usando "+usa.nome+"\n");
	}
void b(String scrivo)
	{
	System.out.println(scrivo+"\n");
	}
}
---------------------------------------------------------------------------------------------------------------------------------------
Per chi non fosse ancora esperto l'esecuzione si ottiene con "java
deadl" dopo aver opportunamente settato la var di ambiente CLASSPATH con
il percorso dove sono contenute le due classi uscite dalla comilazione
(informazione inutile, spero)
Ciao e grazie a tutti!!


2. Ti consiglio di metterti piu' spesso in dubbio
Ciao,
    Bruno.
---
| Bruno Bossola
| A Java Software Engineer :-)
| 
http://members.xoom.it/bbruno
| 
http://digilander.iol.it/bbossola

 (informazione inutile, spero)
Chi non è esperto, dubito sappia cosa sia un deadlock, e non penso si metta
a debuggare il tuo codice.
Marco
              \|/
             (o o)
+-------oOO---(_)---OOo-------+
|  Marco Napolitano   'NAPO'  |
|  
na...@alinet.it
 [max 4Mb]   |
|                             |
|  ICQ#: 19577419             |
+-----------------------------+

Grazie per le risposte.
OK. Ho risolto il problema dichiarando due variabili reference per le
istanze "ista" locali al main e togliendo "static" dalle globali
all'oggetto. Ora il s.w. funziona perfettamente andando in deadlock. A
questo punto mi chiedo a cosa serva il meccanismo di lock sulle istanze
di classe se, per prevenire deadlock di un tipo, ne crea altri meno
individuabili che si verificano quando con un metodo sincronizzato di
una istanza chiama un metodo sincronizzato di un'altra istanza che fa
uso di un metodo sincronizzato della prima. Saranno casi sicuramente
sono meno probabili ma anche meno individuabili e gestibili.
Riporto il codice corretto e "funzionante".
------------------------------------------------------------------------------------------------------------------------------------------
import java.lang.*;
public class deadl extends Thread
{
ista fantoc1,fantoc2; // Non possono essere static altrimenti sarebbero
comuni ai due oggetti "deadl" che avrebbero, quindi, gli stessi
riferimenti.
String nome;
deadl(ista fantoc1, ista fantoc2, String nome)
	{
	this.fantoc1=fantoc1;
	this.fantoc2=fantoc2;
	this.nome=nome;
	}
public static void main(String args[])
	{
 	deadl child1, child2;
	ista fantoc1,fantoc2; /*Qui dichiaro variabili reference locali per gli
oggetti "ista". Infatti non posso utilizzare variabili static allo scopo
perche' sarebbero comuni a tutti gli oggetti deadl creati ed
assumerebbero gli stessi valori in tutti gli oggetti: il valore dato
dall'ultimo costruttore chiamato.*/
	fantoc2 = new ista((String)"bicicletta");
	fantoc1 = new ista((String)"macchina");
	child1 = new deadl(fantoc1,fantoc2,"Pippo");
	child2 = new deadl(fantoc2,fantoc1,"Topolino");
	child1.start();
	child2.start();
	}
public void run()
	{
	System.out.println(nome+": ora chiamero' : "+fantoc1.nome+"-> a(-)");
	fantoc1.a(this,fantoc2);
	}
}
class ista
{
String nome;
ista(String nome)
	{
	this.nome = nome;
	}
synchronized void a(deadl serve, ista usa)
	{
	System.out.println(serve.nome+"-> Sono in: "+nome);
	try {
		serve.sleep(2000);
		}
	catch (Exception e) {
		System.out.println("Ho perso il timer (:-(");
		}
	usa.b(nome+": sto usando "+usa.nome);
	}
synchronized void b(String scrivo)
	{
	System.out.println(scrivo);
	}
}
------------------------------------------------------------------------------------------------------------------------------------------


1. Ho scritto su questo N.G. appunto per mettermi in dubbio. 
2. Non mi conosci per niente.
Comunque grazie per la risposta.


Di niente, comunque il mio e' semplicemente un consiglio su come affrontare i problemi:
dubita sempre prima di te stesso. Io ad esempio non lo so fare ancora, ma non ho problemi
ad ammetterlo: a volte la mia esperienza mi porta a pensare che il sistema sbagli. 
Purtroppo, e' successo un'unica volta in tutta la mia vita. E, nel caso in oggetto, era
pure colpa di una JVM Microsoft :-D (il mitico bug del fattoriale)
