a cura di Dario Dariol
 
 
    Soluzione Esercizio 001 - Thread
    L'esercizio proposto lo scorso mese riguardava i thread di Java e chiedeva quali erano tutti i possibili risultati che una qualsiasi JVM potesse generare in uscita di 3 specifici casi.
    Tabella 1: Soluzione totale e completa dell' Esercizio 001

     

    Possibile Stampa (i-j) Esempio 1
    (senza synchronized
    e senza volatile)
    Esempio 2
    (con synchronized)
    Esempio 3
    (con volatile)
    minimo valore stampabile -n 0 -n
    massimo valore stampabile +m 0 +1
        con n e m interi positivi grandi a piacere.
    La specifica formale di come si comportano thread, synchronized, lock, monitor e volatile si può trovare in JLS, mentre una definizione meno formale e più sintetica è riassunta dai seguenti punti:
    1. ogni programma Java (o, meglio, ogni Java Virtual Machine JVM) possiede 1 memoria condivisa (ad es. la RAM) per le variabili di tutti i thread e n aree locali (ad es. registri) per gli n thread in esecuzione accedibili ciascuna solamente all'n-esimo thread in esecuzione;
    2. ogni thread lavora sempre su copie di tutte  le variabili di un programma copiandole (quando più gli pare e piace ma comunque prima del loro uso) dalla memoria condivisa alla memoria locale;
    3. ogni thread è libero di ricopiare (quando più gli pare e piace ma comunque dopo il loro uso) le copie delle variabili che ha modificato dalla sua area locale alla memoria condivisa del programma;
    4. ogni thread è obbligato a leggere il valore di una variabile volatile dalla memoria condivisa subito prima di un suo uso e di ricopiarla nella memoria condivisa subito dopo il suo uso;
    5. ogni thread all'ingresso di una qualsiasi synchronized è obbligato a:
        • scrivere tutte le variabili che ha modificato dalla sua memoria locale alla memoria condivisa;
        • leggere tutte le variabili di un programma dalla memoria condivisa alla sua memoria locale;
    6. ogni thread all'uscita da una qualsiasi synchnonized è obbligato a scrivere nella memoria condivisa tutte le variabili che ha modificato nella sua memoria locale;
    7. la synchronized su uno stesso oggetto Obj è un punto di lock per tutti i thread che tentino di eseguirla e quindi un solo thread alla volta può entrare in una synchronized e finché questo thread non esce tutti gli altri thread su synchronized dello stesso oggetto Obj sono bloccati e non possono girare (eccetto che per l'uso di wait che però in questo caso non ci interessa perché non usata nel testo dell'esercizio).
    Le regole 2 e 3 si applicano all'esempio 1, la regola 4 si applica all'esempio 3, mentre le rimanenti regole 5-7 spiegano il risultato dell'esempio 2.

    Nota 1 : Questo esercizio è un classico esempio per verificare la conoscenza dei thread da parte degli sviluppatori Java. Nell'ultimo anno ho proposto questo test a varie decine di amici e colleghi e quasi tutti mi hanno fornito -n..+1 (invece che -n..+m ) come risposta al primo esempio. È stata una risposta abbastanza sconfortante dato che i thread sono un asse portante di Java (a differenza di altri linguaggi, come il C o il C++ dove sono stati aggiunti a posteriori al run-time system e non sono presenti nel linguaggio stesso sin dalla sua fondazione) e la loro non-conoscenza può portare a gravi problemi nelle applicazioni basati su di essi.

    Nota 2: Contravvengo alle regole del gioco  che io stesso mi sono dato e vado a parlare un po' delle JVM attualmente disponibili. Ebbene se provate sperimentalmente ad eseguire l'esercizio potrete vedere che in quasi tutte le JVM la tabella dei risultati sperimentali è la seguente:

    Tabella 2: Soluzione parziale e incompleta dell'Esercizio 001


     

    Possibile Stampa (i-j) Esempio 1
    (senza synchronized
    e senza volatile)
    Esempio 2
    (con synchronized)
    Esempio 3
    (con volatile)
    minimo valore stampabile 0 0 0
    massimo valore stampabile +1 0 +1

    Questa tabella è ovviamente corretta, perché copre un sottoinsieme di quella generica che è stata fornita all'inizio di questo esercizio, ma non è completa. Se  i programmi Java che noi scriviamo si basassero su arbitrarie regole dedotte dalla precedente tabella allora essi non sarebbero portabili sulle varie piattaforme perché potrebbe sempre esistere delle JVM corrette che fornirebbero un risultato inatteso (ad esempio: i-j=-27).
    A buon intenditor poche parole!

    Regole del gioco

    I quiz presentati in questa rubrica trattano esclusivamente del linguaggio Java, così non sono richieste conoscenze di applets, servlets, Beans, etc.. Le uniche classi predefinite che possano eventualmente essere utilizzate sono quindi solo quelle appartenenti al package java.lang (classi come ad esempio: Thread, Class, ClassLoader, System, Runtime, etc...). Per risolvere i quiz non serve inoltre editare, compilare o testare nessun tipo di codice. Si tratta di quiz mentali che devono essere risolti solo con la testa e non con il computer. Quindi:

    • Non bisogna compilare ed eseguire nessun pezzo di codice: non sono interessato a sapere che con certe implementazioni della JVM si ottengono certi risultati mentre con altre implementazioni altri risultati. Sono invece interessato a quali siano l'insieme di risultati validi così come specificato dal linguaggio Java: cioè quali sono i risultati che un buon programmatore Java si può aspettare da una qualsiasi JVM che soddisfi le specifiche di Java?
    • Non occorre che inviate una soluzione del quiz a me o alla rivista. La soluzione sarà fornita nel prossimo numero. Una volta nota la soluzione (quindi solo dal prossimo mese in poi) potete allora eventualmente contestarla e/o commentarla inviandomi una email. Io sarò ben lieto di pubblicare e discutere tutti i pareri ricevuti.
 




MokaByte®  è un marchio registrato da MokaByte s.r.l.

Java® è un marchio registrato da Sun Microsystems; tutti i diritti riservati

E' vietata la riproduzione anche parziale
Per comunicazioni inviare una mail a
mokainfo@mokabyte.it