C# / Async programlama ve Thread Kavramı 1

Async programlama bölümüne geçmeden Thread ve multithread yapılarından bahsetmek istiyorum. Thread yapısından bahsetmeye başlayarak yazıya başlayalım. Multithreading, thread scheduler tarafından yönetilir. CLR tarafından OS’ye delegate edilen bir fonksiyondur. Scheduler, her thread yapısının makul bir execution süresi içerisinde tamamlanacağını garanti eder. Bekleyen veya blocklanan threadler CPU zamanını harcamazlar.

Tek işlemcili bilgisayarlarda, thread scheduler hazırda çalışmak için bekleyen thread yapılarını belirli scheduling algoritmalarına göre işleme almaktadır. Her seferinde tek thread çalışmaktadır. Çok işlemcili bilgisayarlarda ise, birden fazla thread aynı anda çalışabilmektedir. Bu sayede scheduling algoritmaları ile daha efektif işlem süreleri içerisinde işlemleri tamamlamaktayız.

Thread vs Process

Thread yapıları işletim sistemi işlemlerine benzemektedir. OS içerisinde işlemler birbirine paralel olarak çalışmaktadır. Thread yapısında ise, threadler bir process içerisinde birbirlerine paralel olarak çalışmaktadırlar. İşlemler birbirlerine tamamen izoledir. Threadler birbirlerine tamamen izole değillerdir. Aynı hafızayı paylaşırlar bundan dolayı birlikte çalışan threadler arasından veriler rahatça paylaşılmaktadır.

process-thread

Thread ve Task yapısının kullanım örneklerine geçmeden önce bazı kavramları netleştirelim. Sıklıkla kullanılan bir örnek üzerinden anlatacağım. Restaurantta yumurta ve tost siparişi geldiğini düşünelim.

  • Synchronous: Önce yumurtayı pişir. Ardından tostu hazırla.

 

singlethreaded
sync single thread

 

multithreaded
sync multithread
  • Asynchronous – single threaded: Yumurtayı mutfakta pişirmeye başla bekle. Ardından tostu makinede hazırlamaya başla ve bekle. Bekleme esnasında yeni sipariş gelirse al. Pişirme süreleri bitince müşterilere servis yap.

 

async single thread
async single thread

 

  • Asynchronous –  multithreaded: 2 yeni aşçı işe alalım. Biri sadece yumurta pişirsin. Diğeri ise sadece tost hazırlama işini halletsin. Mutfakta malzeme kullanırken birbirleri çakışmalarını engellememiz lazım. Ayrıca her ikisinede maaş ödemek durumundayız.

 

async multithread
async multithread

 

Async programlama ile sistemin esnekliği ön plana çıkar. Örneğin; uzun bir hesaplama yapılacağı zaman async programlama ile yapılırsa arka plan’da çalışan thread içerisinde bu işlem halledilir. Sistem ön planda hala esnek durumda kalacaktır.

Paralel programlama ise farklıdır. Her ne kadara bu yazıda bahsetmeyecek olsak bile bahsetmekte fayda olduğunu düşünüyorum.  Paralel programlama ile sistemin CPU performansı gibi özellikler ön plandadır ve tüm çalışan thread yapıları tek bir işlemi yapmak için çalışır. Belirli bir task’ı birden fazla thread kullanacak hızlıca tamamlamaktır. Task’ı tamamlamak için birden fazla kaynak kullanmak olarak düşünebiliriz.

Thread

Teorik girişten sonra artık console application üzerinde threadler ile ilgili işlemlere başlayalım. Aşağıdaki örnekte WriteY() adlı metod thread tanımlanarak çağrılmıştır. Console uygulamasının çalıştığı main metodu içerisinde i  değişkeni 0’dan 100′ e kadar giden for içerisinde “x” ekrana yazılacak. WriteY içinde ise aynı şekilde for döngüsü içerisinde y yazılacaktır.

thread01

Program çıktısı her seferinde farklı olacaktır. Çünkü thread schedular tarafından düzenlenen çalışma sırası her seferinde farklı çalışma öncelikleri ile threadleri tamamlayacaktır.

thread01output thread01output2

Lambda ifadeler kullanarak daha kısa thread tanımları da yapabiliriz.

thread01lambda

Threadler ile çağırdığımız metodlara parametrede gönderebiliyoruz.

thread02

Thread.CurrentThread.Name özelliği ile çalışan thread’in ismini öğrenebiliriz. Thread ismi ayarlamak için threadName.name = “threadismi” şeklinde tanımlama yaparız.

Oluşturduğum tüm threadler default olarak “foreground (ön plan)” şeklinde tanımlanır. Uygulama tüm foreground threadler tamamlanınca biter. Thread özelliği “background (arka plan)”  olarak değiştirilirse, background thread devam etse bile uygulama bitebilir. Bu durumda background thread aniden kesilmiş olacaktır. threadName.Isbackground = true biçiminde tanımlama yapılarak özellik değiştirilebilir. threadName.Join() metodunu çağırarak tüm threadlerin bitmesini bekleyip programı öyle sonlandırabiliriz.

Thread.Sleep (TimeSpan.FromHours (1));  // 1 saat bekle

Thread.Sleep (5000);                     // 5 saniye bekle

Threadlerin Sleep veya Join durumlarında beklemeleri esnasında thread blocklu durumdadır ve CPU kaynaklarını harcamaz.

Aşağıdaki örnekte _field değişkeni ThreadStatic olarak tanımlanmıştır. Bu tanımlama ile _field değişkeni her thread için farklı olacaktır. Şöyle düşünelim ilk thread içerisinde  1’den 10’a kadar döngü içerisinde artıp ekrana çıktı olarak gösterilecektir. Diğer thread başladığı zaman o thread için _field değeri 0 olduğundan 0’dan 10’a kadar tekrardan artış olacaktır. ThreadStatic özelliği eklenmemiş olsa diğer thread için artış 10’dan başlayıp 20’ye kadar olacaktı.

thread022

Ekran görüntüsü

thread021

Thread pooling yapısı ile performans açısından thread yapılarını daha verimli kullanabiliriz.

Tasks

Async programlama ile daha sıklıkla kullanılan Task yapısı thread yapısına göre üst seviyede. Task yapısını kullanarak daha gelişmiş işlemler yapabiliriz. Thread pooling yapısını otomatik olarak kullanıp birbiri ardına eklenebilecek olan işlemleri daha iyi organize etmektedir.

Aşağıdaki yapıda tasks adında türü task olan bir dizi oluşturduk. Bu dizi 3 task değeri alacaktır. Task tanımlamalarımızı yaptıktan sonra Task.WaitAll(tasks) metodu ile tüm taskların çalışıp biteceğini garanti ettik. Aynı thread yapısında bulunan join() metodu gibi

task01

task011

Bu yazıda thread kavramına giriş yaptık. Ardından Task kavramına kısaca değindik. Diğer yazılarımda async ve await ile yapılan async programlama gibi kavramları anlatmaya devam edeceğim. Daha detaylı bilgi ve işlemler için çeşitli kaynaklara bakabilirsiniz.

Önemli linkler

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s