Progettazione di applicazioni multi-threading

 

L'obiettivo di progettare una applicazione multi-threading - oltre a garantire che funzioni correttamente - è di scriverla in modo comprensibile e che aiuta a modificarla e evolverla con tempi e sforzi sostenibili. 

Facendo manutenzione e evolvendo l'applicazione mi troverò ad esempio a cercare risposta a domande come queste, e vorrò riuscire a farlo senza bisogno di sacrifici eroici :

  • Sto aggiungendo una nuova classe all'applicazione, quanti thread avranno accesso contemporaneo all'istanza della classe?

  • Sto modificando il metodo di una classe per aggiungergli chiamate a metodi di altre classi, dovrò aggiungere dei lock ? quali e dove ?

  • Ho necessità di distribuire  in 4 thread il carico lavoro che la applicazione ora sostiene su 2 thread , come devo sincronizzazione i 2 nuovi thread ?

 


E' singolare che le applicazioni multi-utente che accedono a un data-base sono molto più semplici da scrivere/modificare/evolvere delle applicazioni multi-threading anche se hanno molte similitudini e molte cose in comune.

I Db relazionali definiscono un modello di programmazione e gestione della concorrenza che bisogna adottare. Nelle applicazione multi-threading  senza questi vincoli uno stesso problema può essere affrontato in una varietà di modi differenti e cosi la ricerca di una soluzione semplice all'inizio è più impegnativa .  Viceversa una volta acquisito un repertorio di soluzioni efficaci l'unico limite per migliorarle, adattarle e reinventarle è la fantasia.


Update 18-5-2008 sintesi di info e riferimenti utili dai comments

Flynn's Taxonomy
- http://en.wikipedia.org/wiki/Flynn_taxonomy
- http://mugur.roz.md/computer-science/computer-science/images/fig09_02_0.jpg

Monads
- http://blogs.ugidotnet.org/dmantovani/archive/2007/11/26/89935.aspx
- http://channel9.msdn.com/ShowPost.aspx?PostID=358968

 Parallel C#
- http://blogs.ugidotnet.org/dmantovani/archive/2008/05/13/92658.aspx

Microsoft Robotics Studio:
- http://msdn.microsoft.com/en-us/robotics/default.aspx
- http://channel9.msdn.com/ShowPost.aspx?PostID=206574

Questi post sul multi-threading sono limitati a linguaggi Object Oriented su hw con architetture classica Von Neumann (cioè architetture control-flow = istruction-flow di tipo SISD e non Multipme Instruction stream Multiple Data strueam e nemmeno a arcitettura  data-flow; vedi la tassonomia di Flynn). Cioè a .NET C# su PC e Server comuni .

 

Tags :   |

Print | posted @ martedì 6 maggio 2008 06:07

Comments on this entry:

Gravatar # re: Progettazione di applicazione multi-threading
by LudovicoVan at 06/05/2008 18:57

P.P.S.

Gee, the (in)famous self-synchronizing static singleton, finally...

;) -LV
Gravatar # re: Progettazione di applicazione multi-threading
by LudovicoVan at 07/05/2008 17:40

> una altra idea da trovare riguarda come fare quando risorse/variabili condivise sono diverse e cosi c'è anche il rischio di dead-lock

> provo a dire qualcosa nel prox post

Ho letto il post, molto ben fatto, ma ti segnalo che le parti in grigio sono quasi illegibili...

Comunque, nella mia /follia/, al problema che qui sollevi risponderei d'un sol fiato: incapsula a piu' alto livello! (Cioe', incapsula tutto il set di risorse condivise.) Ovviamente, fra il dire e il fare c'e' di mezzo il mare...

-LV
Gravatar # re: Progettazione di applicazione multi-threading
by LudovicoVan at 08/05/2008 05:40

Of course: basta mettere il foglio sotto una lampada a incandescenza per 30+ secondi...

-LV
Gravatar # re: Progettazione di applicazione multi-threading
by LudovicoVan at 08/05/2008 05:46

> e scommetto c'è modo di riuscirci rispettando oltre l'incapsulamento anche la suddivisione di responsabilità tra oggetti

Se e' una domanda seria: si', si tratta di incapsulare in un contesto che non si limta ad esporre una facciata, bensi' gestisce l'orchestrazione; cioe' il tutto e' maggiore della somma delle parti. Hmm, mi sa che la domanda non era troppo seria...

Scherzi a parte, ho letto anche il tuo articolo no. 3: molto interessante! Probabilmente ho descritto un possibile approccio al "modello a competizione". D'acchitto non saprei se discorso simile si puo' estendere al "modello a sincronizzazione". Ci pensero'...

-LV
Gravatar # re: Progettazione di applicazione multi-threading
by LudovicoVan at 08/05/2008 20:08

Se ti sto capendo bene, non rompi l'incapsulamento, semmai stratifichi (o "wrappi"). Ciascun oggetto incapsula la sua propria sincronizzazione, mentre a piu' altro livello ulteriormente incapsuli l'orchestrazione di tali sincronizzazioni. Un po' come le matrioske. Il tutto ad uso dei vari consumer e *rigorosamente* trasparente ad essi (il che resta il criterio ultimo da rispettare).

Comunque un esempio qui potrebbe valere piu' di mille parole. Appena riesco, provo a mettere in piede una sorta di proof of concept, magari proprio a partire dal codice C++ che ho dovuto scrivere per la suddetta libreria matematica.

Se ce la faccio, ti faccio sapere!

-LV
Gravatar # re: Progettazione di applicazioni multi-threading
by LudovicoVan at 12/05/2008 03:52

Fin qui mi pare di esserci... c'e' in realta' qualcosa che mi "puzza", ma potrebbe banalmente essere la mia riluttanza per la terminologia OO delle "responsabilita'" applicata alla ClientConnectedList, che mi sembrerebbe una banale data structure; comunque, procedi pure...

-LV
Gravatar # re: Progettazione di applicazioni multi-threading
by LudovicoVan at 14/05/2008 01:19

Lo smell si conferma. Per il resto, ok, procedi pure.

BTW, poi ti faccio vedere un esempio che e' venuto fuori ad una recente intervista (sono di nuovo a caccia di lavoro), in cui c'e' un dead-lock potenziale, il quale probabilmente si trasforma in dead-lock attuale in uno scenario in cui i carichi sono significativi.

Ti anticipo solo, e lo ritengo un punto di ragionamento essenziale, che tale potenzialita' intrinseca sorge a causa di un errata (nel senso appunto delle possibili conseguenze nefaste) definizione del *dominio dei dati*!!

-LV
Gravatar # re: Progettazione di applicazioni multi-threading
by LudovicoVan at 14/05/2008 23:37

BTW, tornando al modello a sincronizzazione vs il modello a composizione, cfr. anche questo rapido (ma non indolore! :) scambio a partire da un post sempre di Daniele Manotovani:

Parallel C#
http://blogs.ugidotnet.org/dmantovani/archive/2008/05/13/92658.aspx

L'enfasi sui DATI (la primitiva assoluta che incapsula la complessita' reale del dominio) mi sembra sempre piu' significativa...

-LV
Gravatar # re: Progettazione di applicazioni multi-threading
by LudovicoVan at 15/05/2008 01:04

P.S.

Last but not least:

Il Microsoft Robotics Studio e' JavaScript based...!!!

(Non so quanto e' rigorosa, ma so che esprime l'essenziale.)

-LV
Gravatar # re: Progettazione di applicazioni multi-threading
by LudovicoVan at 15/05/2008 03:46

luKa:

> questo codice legacy ha di buono che ogni classe implementa e incapsula il suo locking

Se proprio non vuoi/puoi toccare il codice preesistente, l'unica strada per me e' appunto quella di incapsulare l'extra-complessita' del locking in un wrapper, che diventa il modulo (o oggetto) con cui dall'esterno ci si interfaccia.

Si tratta quindi di una classe che incapsula l'orchestrazione. In questo modo gli sviluppatori che devono utilizzarla non avranno piu' quel problema. Il costo di astrarre quella funzionalita' in una classe a piu' alto livello secondo me e' trascurabile perche' comunque il 90% dello sforzo e' in ogni caso capire come funziona il sistema originale.

Un buon ausilio per pensare e disegnare tale orchestrazione per me e' ragionare in termini di macchina a stati, con l'ausilio di state e sequence diagrams. Il problema, in un certo senso, diventa algoritmico (event-driven) piuttosto che funzionale (data-driven).

Infine, lo stesso wrapper, per quanto nato per l'orchestrazione, puo' e dovrebbe essere il punto di riferimento per ulteriori estensioni. Di sicuro resta il punto di riferimento non ulteriormente scorporabile di qualunque refactoring.

Resta detto che, se l'unico pregio del codice originale e' che "incapsula il suo locking", a maggior ragione ti direi che lo puoi/dovresti cestinare e riscrivere, perche' e' il modello a monte che e' broken e l'extra-complessita', compresi i problemi di dead-lock, deriva proprio/solo da quello.

Bottom line: Se construisci un wrapper oggi, domani dovrai costruirne un altro... e se ripensi al refactoring e alla non-scorporabilita' ti fai anche un'idea delle proporzioni del problema.

-LV
Comments have been closed on this topic.