Freitag, 6. Juli 2007

Mein aktuelles Steckenpferd: Software Transactional Memory

Früher hatte Vati die elektrische Eisenbahn als Steckenpferd. Und heute? Heute hat Vati einen Windows Media Edition PC, der ihn nicht mehr zur Ruhe kommen lässt ;-) Nur ich tanze da wohl aus der Reihe. Aber ich habe ja auch kein Auto. Die Media Edition interessiert mich nicht, dafür aber Software Transactional Memory (STM). Das (!) ist cool. Viel cooler als an einem PC rumzuschrauben :-)

Und was soll so ein STM? Der macht z.B. die Programmierung mit mehreren Threads einfacher. Statt den Zugriff auf gemeinsame in-memory Ressourcen durch ausgeklügelte Sperren zu synchronisieren, arbeiten Sie einfach mit Transactionen. Genau: Transactionen wie bei Datenbanken - nur eben nicht auf persistenten Daten, sondern im Hauptspeicher!

Wem das aber noch nicht cool genug erscheint, der kann damit auch ohne Multithreading Undo-Lösungen basteln. Und das nicht nur auf einer Ebene, sondern auch echt geschachtelt. Das kann nicht mal SQL Server :-)

Und wer das noch nicht cool findet, der kann auch verteilte Transaktionen fahren: Mit System.Transactions eine Transaction öffnen, auf SQL Server zugreifen und Veränderungen im STM vornehmen - und am Ende alles zusammen committen oder zurückrollen.

Hier das kanonische Beispiel für Transaktionen mit dem .NET Software Transactional Memory (NSTM) realisiert: Überweisung eines Betrags von einem Konto auf ein anderes.

    1 INstmObject<double> myAccount;

    2 INstmObject<double> yourAccount;

    3 

    4 myAccount = NstmMemory.CreateObject<double>(1000);

    5 yourAccount = NstmMemory.CreateObject<double>(500);

    6 

    7 using (INstmTransaction tx = NstmMemory.BeginTransaction())

    8 {

    9     double amountToTransfer = 150;

   10 

   11     myAccount.Write(myAccount.Read() - amountToTransfer);

   12     yourAccount.Write(yourAccount.Read() + amountToTransfer);

   13 

   14     tx.Commit();

   15 }

   16 

   17 Console.WriteLine("My account balance: {0}", myAccount.Read());

   18 Console.WriteLine("Your account balance: {0}", yourAccount.Read());

In Zeile 16 hat der Transfer entweder komplett geklappt oder gar nicht. Inkonsistenzen, die durch einen Fehler in der Verarbeitung (Zeilen 9 bis 12) auftreten könnten, haben keine Chance, nach außen "durchzulecken". Wie gesagt: das ist wie mit Transaktionen bei Datenbanken. Wer sich den Code genau ansieht, wird das feststellen und auch sehen, dass er sehr dicht an Code ist, den man mit "normalen" Variablen geschrieben hätte.

NSTM ist mein Versuch der Implementation von STM, nachdem ich von dem Konzept neulich gehört hatte. Da war ich fasziniert und hab ne Menge drüber gelesen. Aber dann musste ich es einfach ausprobieren. Allemal, da die verfügbaren Implementationen alle irgendwie hinken. Entweder in Java realisiert oder unter Zuhilfenahme von Unmanaged Code oder nur für Haskell oder irgendwie nicht dem "normalen" Programmiermodell entsprechend, das wir von Transaktionen kennen. Also hab ich das gemacht, was alle Entwickler gern tun: ich habe meine eigene Infrastruktur gebastelt. Und es hat Spaß gemacht :-)  Aber dafür ist ein Steckenpferd ja auch da.

Wer mehr über NSTM erfahren will, kann in meinem englischen Blog eine ausführliche Darstellung lesen. Das Thema hab ich für international interessant gehalten und deshalb dort zuerst darüber geschrieben. Man sehe es mir in der deutschen Community nach.