lunedì 30 aprile 2012

Modificatore volatile in Java

La piattaforma Java supporta la programmazione concorrente tramite il concetto di thread di esecuzione. Una applicazione Java può avere più flussi di esecuzione paralleli, ciascuno rappresentato da un oggetto java.lang.Thread.

Thread di esecuzione - Immagine recuperata da Internet


Quando due thread hanno necessità di interagire tra loro devono "sincronizzarsi" in modo da evitare situazioni non deterministiche (in cui il risultato varia da un'esecuzione all'altra a causa di variazioni, anche piccole, nei tempi di esecuzione dei singoli step elaborativi). Ed è proprio la sincronizzazione uno degli aspetti più complessi della programmazione concorrente.

La sincronizzazione è caratterizzata da due aspetti in un certo senso ortogonali tra loro:
  1. mutua esclusione
  2. visibilità
La mutua esclusione è utilizzata per evitare l'accesso concorrente a strutture dati condivise. La mutua esclusione in Java si basa sul concetto di monitor. Ad ogni oggetto Java è associato un monitor che offre le classiche primitive di lock e unlock. Il runtime garantisce che un solo thread per volta può ottenere il lock su uno stesso monitor. Utilizzando un monitor è possibile impedire l'accesso concorrente a una struttura dati condivisa.

Java mette a disposizione, oltre alle primitive di basso livello sul monitor, anche altri costrutti di sincronizzazione quali i metodi e i blocchi "synchronized" e l'intero package java.util.concurrent. Queste feature non essendo oggetto di questo articolo non saranno però illustrate ulteriormente (magari potremmo ritornarci in futuro, se interessa).

La visibilità è invece un aspetto po' più subdolo. Esso riguarda la capacità di vedere il valore corrente di una varibile da parte dei thread differenti rispetto a quello che ha modificato la variabile (sembra complicato ma leggendo di seguito dovrebbe risultare più chiaro).

Per motivi di prestazioni, la piattaforma Java può conservare in una cache locale a ciascun thread (o in registri della CPU) il valore delle variabili anche quando queste sono condivise tra più thread. Se il valore di una variabile è modificato in un thread, nella cache di tutti gli altri thread potrebbero esserci valori non più aggiornati. Il programmatore deve quindi sempre usare meccanismi di controllo della visibilità per assicurarsi che i thread vedano i valori corretti delle varibili quando accedono a dati condivisi.

La visibilità tra thread è sicuramente garantita usando le primitive di lock/unlock di un monitor (quelle usate per gestire la mutua esclusione). Nella seguente figura sono mostrati i due thread A e B sincronizzati tramite il monitor M. Il modello di memoria Java garantisce che i valori delle variabili disponibili nel thread A, immediatamente prima dell'unlock di M, siano visibili al thread B, subito dopo che questo ha ottenuto il lock di M.

Figura dal sito IBM

Esiste tuttavia anche un modo diverso per forzare la visibilità di una variabile condivisa e che non richiede l'utilizzo di primitive di lock/unlock: il modificatore volatile. Tale modificatore può essere utilizzato per informare la piattaforma che una variabile è acceduta da più thread e si intende garantire la visibilità del valore corrente della variabile (senza bloccare i thread quindi con un miglioramento delle prestazioni dell'applicazione).

Un esempio classico di utilizzo di questo costrutto è il seguente: supponiamo di avere un thread che effettua un lavoro in background finché non gli viene segnalato di terminare. La richiesta di terminazione può essere registrata in una variabile shutdownRequested di tipo boolean che, in generale, sarà impostata da un differente thread.

In questo scenario non vi è un conflitto tra i due thread (perché il thread che lavora in background accede alla variabile shutdownRequested in sola lettura) e non è pertanto necessario usare un monitor per proteggere la risorsa condivisa. Tuttavia il modello di memoria di Java richiede che, per garantire la visibilità del valore della variabile condivisa tra i due thread, sia comunque utilizzato un costrutto di sincronizzazione. In questo caso in cui un monitor sarebbe eccessivo... si può ricorrere al modificatore volatile. Di seguito è riportato il frammento di codice.

volatile boolean shutdownRequested;
...
public void shutdown() { 
  shutdownRequested = true; 
}

public void doSomeWork() {
    while (!shutdownRequested) {
        // ciclo thread1
    }
}

Cosa accade se "dimentichiamo" il modificatore volatile? Magari su alcune implementazioni della piattaforma Java il programma continuerà a funzionare correttamente... tuttavia in altre implementazioni (in particolare quelle dedicate a sistemi multiprocessore) l'esecuzione del programma potrebbe far andare il thread di background in un loop infinito: il valore true della variabile shutdownRequest (impostato da un altro thread) non sarebbe visibile al thread di background che continuerebbe a ciclare sul valore iniziale false memorizzato nella propria cache!

Chi volesse approfondire... sul sito Oracle, al link indicato di seguito, sono pubblicate le specifiche della JVM con un capitolo dedicato al modello di memoria di Java (link: Threads e Locks). Un testo specifico sulla programmazione concorrente è Java Concurrency in Practice.

sabato 28 aprile 2012

Assinform: IT - contrazione del 4,1%

Nel Rapporto Assinform sull’andamento del settore dell’Information & Communication Technology nel 2011 evidenzia una contrazione del mercato IT pari al 4,1% in contrasto al resto del mondo, dove l’IT cresce a +2,4%.

Peggio dell’Italia ha fatto solo la Spagna con un mercato IT sceso di -5,3% a fronte di una media europea di +0,5%, con la Francia attestata a + 0,3%, la Germania a +2,3% e il Regno Unito a -0,7%.
 
Le previsioni per il 2012 comunque non sono confortanti : -2,3%.

Possibile che non ci chiediamo i motivi? E non mi si venga a dire che è per via dell'Art. 18!!!

venerdì 27 aprile 2012

Intelligenza collettiva, contesto lavorativo, innovazione

Oggi si sente parlare moltissimo di intelligenza collettiva come strumento che permette a una comunità di cooperare mantenendo prestazioni intellettuali affidabili. L'idea di base è che un gran numero di unità possano cooperare tanto strettamente da divenire indistinguibili da un singolo organismo. Anche la comunità scientifica può, secondo alcuni, essere considerata una sorta di intelligenza collettiva. Così come una organizzazione con tutte le sue professionalità.

E' indubbio che il fermento e l'energia che si sviluppano nell'ambito del contesto lavorativo e lo scambio continuo con i colleghi, in special modo con quelli più esperti, possono contribuire significativamente al successo di un'organizzazione. Trovarsi in un contesto lavorativo "stimolante" è uno degli aspetti che personalmente considero più importanti per favorire i processi di innovazione.

Fortunatamente nel mio contesto lavorativo ho la possibilità di incontrare moltissimi esperti su ogni argomento. A dire il vero non passa un giorno che non conosco un nuovo "massimo esperto in qualche settore". E oggi mi sento di poter dire con la massima serenità che comunque si fissa un ambito di comptenza A, sicuramente mi è stato presentato qualcuno qualificato come il massimo esperto di A.

E' proprio questo a rendere il mio lavoro molto interessante! Anche perché sono affascinato da come i massimi esperti, per nulla intimoriti dall'importanza della qualifica con cui sono stati presentati, mi parlano degli argomenti di propria competenza rendendomi edotto delle più interessanti novità (che non avrei mai potuto scoprire in autonomia) e mi rivelano i segreti più reconditi della materia.

Lo ammetto: una volta ho inizialmente dubitato della reale competenza della persona che mi veniva presentata come "il massimo esperto" di uno specifico settore. Forse sarà stata invidia, forse presunzione, fatto sta che mentre costui cercava di erudirmi su come, grazie al suo prezioso sapere, io potessi risolvere alcuni problemi lavorativi nel suo campo di espertise, io trovavo i concetti, pur abilmente esposti in una forma adatta a renderli comprensibili anche a un profano come me, comunque ostici da capire e apprezzare fino in fondo. In brevissimo tempo il mio dubbio iniziale è stato fugato da una profonda riflessione con un risvolto a dir poco frustrante: sicuramente era la mia pregressa formazione sulla specifica materia ad essere carente. E le misconcezioni che nel tempo avevo accumulato non mi permettevano di trarre giovamento dalle molteplici lezioni impartite.

Una situazione che mi ha davvero imbarazzato molto. Per mia fortuna questa condizione mentale caratterizzata da incertezza circa la reale competenza dell'esperto di turno, oggigiorno, capita davvero raramente... praticamente sempre ho modo di verificare la piena attendibilità di tutte le conoscenze elargite dai maestri: la maggior parte di queste conoscenze le trovo rigorosamente riprodotte su Wikipedia! E la cosa mi rincuora un po': non solo io ma anche Wikipedia trae vantaggio dalle conoscenze di questi grandi!

---
PS: purtroppo non ho trovato su Wikipedia alcun riferimento al termine "misconcezione" quindi riporto di seguito una  possibile definizione: misconcezioni sono tutte quelle opinioni incompatibili con quelle correttamente accettate dalla scienza, che possono produrre un sistematico sviluppo di errori di carattere concettuale o contenutistico.

lunedì 23 aprile 2012

Teoria dell'informazione


In Una teoria matematica della comunicazione (wikipedia) - articolo che viene considerato uno dei pilastri fondanti della moderna teoria dell'informazione (wikipedia) - Shannon concettualizza e modella matematicamente il problema della comunicazione attraverso un canale rumoroso.

Il problema consiste nel riprodurre nel modo più preciso possibile in un punto (di Destinazione) un messaggio selezionato in un altro punto (Sorgente).


Problema della trasmissione di informazioni su un canale rumoroso

Come rappresentato nella figura, il messaggio emesso dalla Sorgente è trasformato da un Trasmettitore in un opportuno segnale. Il segnale è inviato tramite un canale (rumoroso) che lo propaga in modo non esatto (aggiungendo rumore) a un Ricevitore. Il Ricevitore trasforma il segnale ricevuto in un messaggio per la Destinazione.

La comunicazione avviene correttamente quando i due messaggi (nella figura a sinistra e a destra del canale di comunicazione) coincidono o sono "sufficentemente simili".

Come si collega questo problema della comunicazione alla definizione di informazione (ciò che [...] supera un'incertezza) vista su wikipedia ? Con la teoria della probabilità...

Se il messaggio emesso dalla Sorgente è un simbolo s selezionato con probabilità p(s) da un insieme predefinito S (detto alfabeto), è possibile caratterizzare il contenuto informativo di s usando un'idea di base molto semplice: più un ricevitore è "sorpreso" (proprio nel senso di sorpresa! - wikipedia) nel vedere il simbolo s, più il suo contenuto informativo sarà alto. Matematicamente il contenuto informativo di s, indicato con I(s) è dato dalla seguente formula - log2 è il logaritmo in base 2

I(s) = - log2 p(s)

In questo senso l'informazione può essere vista come una riduzione dell'incertezza. La trasmissione del simbolo s ha un contenuto infomativo pari a I(s) "bits" (binary units of information, unità di misura dell'informazione).

Supponiamo che la Sorgente produca le informazioni con un lancio di due monete, ciascuna delle quali può produrre, in modo equiprobabile e indipendente, i risultati Testa o Croce. Prima della comunicazione la Destinazione sa che riceverà un messaggio corrispondente a una delle quattro coppie ordinate (Testa, Testa), (Testa, Croce), (Croce, Croce), (Croce, Testa), ciascuna con probabilità 0.25. Detto s il simbolo che corrisponde al risultato del lancio delle due monete, si ha

I(s) = - log2 0.25 = log2 4 = 2

che significa che il contenuto informativo di ciascun simbolo s ha un contenuto informativo di 2 "bits".

Supponiamo ora che i risultati del lancio delle due monete siano trasmessi con due sotto-messaggi distinti, il primo corrispondente alla prima estrazione, il secondo contenente la coppia (ordinata) di risultati per entrambe le monete. Supponiamo inoltre che il lancio della prima moneta abbia prodotto il risultato Testa e che il corrispondente sotto-messaggio sia già pervenuto correttamente alla Destinazione. L'informazione ricevuta con il primo sotto-messaggio ha ridotto l'incertezza: il secondo sotto-messaggio, per essere compatibile con la conoscenza derivante dal primo, può solo contenere una delle coppie ordinate (Testa, Testa) e (Testa, Croce), ciascuna ora con probabilità 0.5. L'informazione ottenuta dal primo sotto-messaggio ha ridotto del 50% l'incertezza sul secondo.

Il contenuto informativo di ciascun sotto-messaggio è infatti pari a 1 "bit".

I(s) = - log2 0.5 = log2 2 = 1

La prima definizione di informazione presente su wikipedia ha quindi una giustificazione nella Teoria dell'Informazione ed è concettualmente diversa da quella proposta immediatamente dopo... anche se le due definizioni sono collegate da "In altre parole"!

Quindi due differenti concetti di informazione:
  1. informazione come contenuto semantico (significato)
  2. informazione come riduzione dell'incertezza