C# Volatile Anahtar Sözcüğü



Derleyiciler kodunuzun daha hızlı çalışabilmesi için çoğu zaman kodunuza mudahalede bulunurlar. Bu müdehaleler kod optimizasyonu olarak bilinir. Ne gibi optimizasyonlar yapılır derseniz. Mesela bir değişken tanımladınız ve hiç çağırmadınız. Bu durumda derleyici bu değişkeni derlenecek kodun içerisine almayarak derlenecek kod boyutunu küçültür. Ayni şekilde yanlışlıkla hiç bir şekilde içine girilmiyecek bir if yazdınız bu sefer derleyici bu if içerisinde yaptığınız işlemleri derlenecek koda eklemeyecektir. İşte tüm bunlar bize performans olarak geri döner. İkinci bir optimizasyon ise microişlemci düzeyinde optimizasyondur. Bu derleyicinin değişkenlerin elde edilmesinde yada tekrar yazılmasında belleğin yada işlemcinin tercih edilmesi ile ilgilidir. Değerin mikroişlemci tarafından belleğe(ram) yazılması ile mikroişlemcideki register bölgesine yazılması arasında büyük fark vardır. Bu fark elbette hız faktörüdür. İşte tam bu noktada ikinci tip optimizasyon kuralını tanımlayabiliriz. Derleyici öyle bloklara rastlayabilir ki, bu bloklar içinde bulunan bir değişkenin değerini her defasında bellekten okuyacağına bu değişkenin değerini bir defaya mahsus olmak üzere mikroişlemcinin ilgili register bölgesine bölgesine kaydeder ve sonraki okumalarda işlemci bellek yerine bu register bölgesini kullanır. Böylece kodunuzun çalışma süresinde önemli sayılabilecek bir azalma görülür.


Bildiğiniz üzere uygulamalar genellikle çoklu iş parçacıklarından(multi thread) ve proseslerden oluşur. Her bir proses diğer bir proses teki değişkene işletim sisteminin izin verdiği ölçüde erişip üzerinde işlemler yapabilir. Aynı şekilde bir iş parçacığıda diğer bir iş parçacığında bulunan değişkene erişip üzerinde çeşitli işlemler yapabilir. Peki bunun bizim optimizasyon kurllarımızla bağlantısı ne? Şöyle ki : derleyici bir değişkenin değerinin farklı bir iş parçacağı tarafından yada farklı bir proses tarafından işleneceği üzerinde durmaz. Bu tamamen işletim sisteminin yönetimindedir. Hal böyleyken bizim yukarıda bahsettiğimiz ikinci optimizasyon tipi bazı durumlarda yarar getireceğiniz zarar getirebilir. Zira optimizasyon adına bir değişkenin değerini her defasında bellekten okuma yerine mikroişlemcideki ilgili register dan okurken o anda farklı bir iş parçacağı yada farklı bir proses hatta ve hatta işletim sistemi sizin erişmeye çalıştığınız değişkenin değerini sizin uygulamanızın mantığına göre değiştirebilir. Bu durumda siz o değişkenin son halini kullanmamış olursunuz. Dolayısıyla programınızda farklı thread lar yada prosesler arasında paylaşılan veya işletim sistemi tarafından değiştirilmesi muhtemel olan değişkenlerinizi optimizasyon kuralına tabi tutmamanız gerekir. Bu durumda  volatile anahtar sözcüğü burada imdadımıza yetişiyor. Bir değişkeni volatile anahtar sözcüğü ile bildirdiğiniz takdirde derleyicinizin optimizasyon ile ilgili parametresini açık tutsanız bile ilgili değişken yukarıda bahsi geçen tehlikeli optimizasyon kurallarına tabi tutulmayacaktır. Yani volatile ile bildirilen değişkenlere programın akışı sırasında her ihtiyaç duyulduğunda değişkenin gerçek yeri olan belleğe başvurulur. 

Volatile aşağıdaki değişken tipleri ile birlikte kullanılabilir.


  • Herhangi bir referans tipindeki değişken ile

  • byte, sbyte, short, ushort, int, uint, char, float yada bool. türünden olan değişkenler ile

  • byte, sbyte, short, ushort, int, yada uint türünden semboller içeren numaralandırmalar(enums) ile

  • unsafe modda iken herhangi bir gösterici türü ile
Bu konuyla ilgili MSDN'de bulunan aşağıdaki örneği inceleyerek konuyu daha iyi anlayabiliriz.

using System;
using System.Threading;

class Test
{
    public static int result;
    public static volatile bool finished;

    static void Thread2()
    {
        result = 143;
        finished = true;
    }

    static void Main()
    {
        finished = false;
        new Thread(new ThreadStart(Thread2)).Start();

        for (; ; )
        {
            if (finished)
            {
                Console.WriteLine("result = {0}", result);
                return;
            }
        }
    }
}
Yukarıda görüldüğü gibi boolean bir değer olan finish değişkeni volatile olarak tanımlanmıştır. Bu programdaki püf nokta finished isimli değişkenin ana thread ve ana thread içinde başlatılan yeni thread tarafından ortak kullanılan bir değişken olmasıdır. Eğer finished değişkeni volatile olarak bildirilmemiş olsaydı, akış thread2 metoduna gelmiş olmasına rağmen Main metodu içindeki if bloğu çalıştırılmayabilirdi. Çünkü derleyici ana thread içinden finished değişkeninine tampolanmış bir bölgeden(register) erişebilir. Bu durumda finished değişkeninin gerçek değeri true olmasına rağmen ana thread de finished değişkeni halen false olarak ele alınır. Bu yüzden finished değişkeninin her durumda son versiyonunu elde etmek için bu değişken volatile anahtar sözcüğü ile bildirilmiştir.

Kaynak : CSharpNedir.com

2 yorum :