Software Transactional Memory ve .NET

Software Transactional Memory (STM), veritabanlarında bulunan transaction yapısının avantajlarını kullanarak kodun herhangi bir parçasında transaction bütünlüğünü sağlayabileceğimiz bir mekanizma. STM'yi direkt olarak kullanabildiğimiz diller (Clojure) olabileceği gibi, Java, C# gibi dillerde de farklı kütüphaneler ile STM desteğini sağlayabiliyoruz. Örnek kodlarda, bulabildiğim en güncel C# STM kütüphanesi olan Shielded'ı kullandım.

Mesela elimizde aşağıdaki gibi bir kod olduğunu düşünelim;

Kod aslında counter 'ı 2 thread kullanarak \(2 \times 10^8\) yapmaya çalışıyor ama thread-safe olmadığı için her çalıştırmada rastgele ve beklenen değerden küçük sonuçlar verecek. Bunu düzeltmek için C#'ın bize sağladığı lock  yapısını kullanıyoruz.

Bu kod bize her seferinde doğru sonucu verecek. Basit bir durum olduğu için lock bloğunu rahatça kullandık. Peki eğer elimizde 2 counter varsa ne yapacağız? Yeni durumda counter1  eskisi gibi çalışsın, buna ek olarak da counter1'in 100'ün katını aldığı her değerde counter2'yi 1 arttıralım. 3. bir thread'le de counter2'yi teker teker arttıralım. Bu durumda kodu nasıl thread-safe yapacağız? Bir örneği aşağıdaki gibi;

Kodu daha basit yapmak için tüm işlemlerde mutex1 'i kullanabilirim ama bu doğru değil, counter2 'yi de bağımsız olarak arttırabilmem lazım. Bir counter daha ekleyince kod gereksiz yere karmaşıklaştı.

Burada alternatif olarak STM'yi deneyebilirim artık.

Son kod ile iç içe bir sürü lock kullanmadan işi hallettim.

Shielded bu kontrolleri dilin verdiği lock yapısı ile değil, nesnelere birer zaman etiketi atayarak ve her erişimde bunu kontrol ederek yapıyor. Nesnenin en son haline erişemediğimiz halde de verdiğimiz kod bloğunu baştan çalıştırıyor. Bu tekrar durumunu göz önünde bulundurarak, blok içindeki Shielded<>  olmayan nesnelere ve I/O gibi transaction dışı işlemlere güvenmemek gerekiyor. Yani, run2 'deki bloğun başına bir Console.WriteLine  yazarsak, her çalıştırmada konsola yazılan satır sayısı aynı olmayabilir.

Son olarak, Shielded kütüphanesi içinde Tree, HashSet, Dictionary gibi yapıların transaction ile çalışan hallerini bulmak da mümkün.