In questa terzaparte si continua ad esporre l’utilizzo del Lazy in ambiti multithread.

Quanto visto nella parte precedente cioè l'utilizzo della classe Lazy senza usare costrutti particolariespone come anche a fronte di più thread tutto funziona correttamente e senza intoppi.

Possono però esistere casi reali in cui si rende necessario avere maggiore possibilità di configurarne il comportamento.

Per esempio l’inizializzatore della classe T, o anche il codice a contorno, può avere al suo interno dei lock o altro, che possono non andare d’accordo con i lock presenti all’interno della classe Lazy, e questa coesistenza può provocare deadlock.

In altre parole come detto l’oggetto Lazy è thread-safe, e quindi per esempio affinché il codice dell’inizializzatore della classe T sia tale vengono usati giocoforza all’interno del framework qualche sorta di lock: questo non solo introduce penalità di perfomance ma può portare (anche se in rari casi) a deadlock che possono occorrere sopratutto a fronte della presenza di altri lock posti nel codice utilizzatore scritto da noi.

Un altro caso può essere legato al fatto che pur essendo in ambiente multithread non siamo interessati al fatto che la classe Lazy sia thread-safe poiché si desidera gestire questo aspetto nel codice consumatore.

In altri termini si desidera delegare la gestione dell’accesso concorrente all’inizializzatore nonché alle proprietà Value e IsValueCreated a codice scritto esternamente da noi, questo con l’ovvio intento di spremere al massimo le perfomance.

Ecco la seconda parte della piccola serie dedicata all'oggetto Lazy<T>. Nel. post precedente ho inziato a esporre i rudimenti iniziali relativi alla classe.

Ora occorre anche ragionare su cosa succede in ambienti multi-thread quando si richiama la proprietà value da Lazy.

Al rientro dalla ferie mi sono trovato a gestire un problema particolarmente rognoso che riguardava tra le altre cose l'utilizzo imporprio della classe Lazy.

Siccome in realtà non conoscevo in modo approfondito questa classe, ho dovuto studiarla e ho verificato come in realtà questa possa essere utile in diversi contesti.

Ho anche ritenuto l’argomento abbastanza interessante e per questo ho pensato di scriverne qualcosa.Spero possa interessare anche Voi.

Iniziamo con il dire a cosa serve: lo scopo del Lazy è quello di gestire in modo efficace un tipo di variabile T molto “pesante” e impegnativa, generalmente rappresentato da una classe (anche se può essere un qualsiasi tipo reference o value).

Con il termine pesante mi riferisco a una classe che gestisce al suo interno molti dati e/o la cui procedura di attivazione è molto onerosa.

In pratica Lazy permette di ottenere l’inizializzazione differita: quindi il tipo T specificato non sarà mai instanziato, e quindi occuperà risorse, sino a quando non verrà utilizzato almeno una volta.

L’utilizzo pratico è relativamente semplice: nella dichiarazione dell'oggetto Lazy si sostituisce a T il nome della classe, e quindi quando occorre un'istanza della classe T si utilizza la proprietà value offerta da Lazy.

Certo, è possibile assolutamente scrivere per nostro conto la logica che permetta di instanziare un oggetto solo quando e se necessario, ma il .Net ci permette di avere questa possibilità che in realtà ci esemplifica non poco il lavoro.

Continuiamo con le speculazioni estive intorno all'argomento del boxing/unboxing e perfomance.

Nel post precedente abbiamo parlato di cosa vogliano dire i termini in oggetto, e abbiamo evidenziate le motivazioni che stanno dietro alle penalità di perfomance proposte per queste attività.

Qui ora acceneremo qualcosa riguardo ai generics.

 Uno dei grossi vantaggi introdotti dal mondo "generics" è legato alle perfomance, oltre che la "type safety".

L'abbiamo già accennato, ma è meglio rispecificare. Con quest'ultimo termine si intendono le attività atte a evitare gli errori derivanti da lavorare con variabili di tipo incerto: la definizione è abbastanza generica, ma sono certo che rende bene l'idea.

Per vedere bene i vantaggi e gli svantaggi vediamo l’utilizzo della classe ArrayList fornita da .Net framework, e che è una delle poche classi che permette l’utilizzo di object come argomento.

Per i pochi che non lo sanno la classe ArrayList rappresenta un semplice array di object la cui dimensione autonomamente e dinamicamente si adatta ai valori inseriti senza dover fare alcunchè.

Essendo che tutte le variabili in .Net derivano da System.Object, sia direttamente che indirettamente, ecci che quindi object è in grado di ospitare qualisiasi tipo di dato.

Può sembrare una stranezza, ma è proprio così: usando ArrayList è possibile aggiungere a questa un intero, una stringa, un oggetto, o comunque una variabile di qualsiasi tipo ci passi per la testa.

Questa "libertà", però, ha conseguenze nefaste, se non è ben gestita.