Singleton Design Pattern (Singlethread & Multithread & Static Initialization)

Singleton design patternde Factory pattern gibi bir creational pattern. Yani aynı şekilde nesne yaratmak amacıyla var olan bir pattern.

   

Bazı nesnelerin application boyunca yaşamasını ve bir başka örneğinin yaratılmamasını isteriz bu gibi durumlarda singleton design pattern bizim için kullanışlı olacaktır.

   

Örneğin bir socket bağlantınız var ve uygulama boyunca açık olan bu bağlantı üzerinden haberleşmek istiyorsunuz veya aynı durum database içinde geçerli olabilir. SocketManager diye bir class'imiz olduğunu düşünün ve bunun bir örneği olsun istiyoruz. Aşağıdaki kod ile devam edelim.

   

   

Kod içinde komutlarda olabildiğince aciklamaya çalıştım. Böylece sürekli olarak yeni bir nesne yaratmak yerine her defasında aynı nesneyi kullanmış oluyoruz.

   

   

Yukarıdaki kod birden cok thread kullanımında güvenli değil çünkü iki thread aynı anda birden cok instance yaratmış olabilir bunu önlemek için Double check locking pattern kullanmalıyız. Bu pattern ile yukarıdaki kodu birden çok threadin mantıklı şekilde kullanmasını sağlayabilriiz. Diğer bir yöntem ise Static initialization.

   

Multithread Singleton

   

Birden çok thread kullandığımızı düşünelim. Threadlerden biri if (activeConnection == null) kontrolunu yaptı, sonuc olarak true aldı ve nesne yaratacak tam bu sırada (nesne yaratılmadan önce null check yapıldıktan sonra) OS ikinci thread'I devreye aldı ve ikinci thread'de if (activeConnection == null) kontrolunu yaptı aynı şekilde bu thread'de sonuc olarak true aldı ve nesne yaratmaya karar verdi. Bu durumda gördüğünüz gibi iki thread ayrı ayrı iki nesne yaratmış oldu. Yani activeConnection = new SocketManager(); kodu birden çok defa çalıştı. Buda Singleton mantığına uymayacak bir yapı oldu. Bunun için C#'da bulunan lock keywordunu kullanarak thread safe bir hale getirebiliriz.

   

   

Yukarıda görüdğünüz gibi ilk olarak bir object yaratıyoruz, bu objectin amacı lock keywordu içerisinde kullanılacak nesneyi tanımlamak.

   

Daha sonra lock(syncRoot) kullanarak scope içerisine aynı anda sadece bir thread girmesine izin veriyoruz. Bu scope'a giren thread işini bitirip scope'u terk etmeden diğer thread'ler lock keywordunde bekliyor.

   

Yaptık mı?

   

Evet artık singleton oldu ama kodu daha güzelleştirmemiz mümkün. Neden?

Nesne yaratılmasındaki sorunu çözdük ama şimdide lock bizim için bir sorun birden cok thread aynı anda lock'lu bölüme ulaşacağı zaman birbirlerini bekleyecekler aslında bu bizim istediğimiz birşey ama her zaman değil, nesne yaratılana kadar durumun böyle olması gerekiyor. Ama sonrasında artık lock'a ihtiyacımız yok, tamda burada double-checkin locking pattern devreye giriyor. Bu pattern sayesinde lock'a girmeden önce bir null check daha yapmalıyız. Yani kod aşağıdaki gibi oluyor.

   

   

Şimdi koda baktığımız zaman ilk önce if (activeConnection == null) yapıyoruz eğer değişken null ise ve yaratılacağını düşünüyorsak lock yapıyoruz ve lock içerisinde tekrar check ediyoruz. Eğer değişken hala null ise bu sefer nesne yaratıyoruz. Böylece eğer nesne zaten yaratılmış ise ilk if'i geçemeyeceği için lock'a girmeyecek ve threadler birbirini her defasında beklemeyecek, sadece activeConnection null ise lock devrede olacak, bu patternde Double-Check Locking pattern. http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

   

Static Initialization

   

Diğer bir yol ise static initialization, nesne yaratma olayını developer'a değil run-time'a devrediyoruz. Böylece static ve readonly olarak yaratılan activeConnection değişkeni uygulama açıldığında bir kez yaratılacak ve sonra istense bile readonly olduğu için değiştirlemeyecek. Böylece multithread'e uygun hale gelecek

   

   


Kodlara aşağıdaki linklerden ulaşabilirsiniz.

https://github.com/altinokdarici/DesignPatterns/tree/master/CreationalPatterns/SingletonPattern   

https://github.com/altinokdarici/DesignPatterns/tree/master/CreationalPatterns/MultithreadSingletonPattern

https://github.com/altinokdarici/DesignPatterns/tree/master/CreationalPatterns/StaticInitializationSingletonPattern

   

Deniz Demircioğlu'na bana kattıkları için özellikle teşekkür ederim.

Yorum ekle

Loading