Sitemap

Multithread Programlama Temelleri

7 min readJun 2, 2024

--

Konu Başlıkları

  • Asenkron ve Multithread Programlama Temelleri
  • Thread Kavramı Nedir?
  • Asenkron ve Senkron Nedir?
  • Asenkron ve Multithread Programlama Nedir?
  • Asenkron ve Multithread Programlama Farkları?
  • Thread Yapılanması
  • Thread Sınıfı
  • Thread Id
  • IsBackground Property
  • Thread State
  • Race Conditions Nedir? Nasıl Önlemler Alınır?
  • Locking Mekanizması
  • Thread.Sleep Metodu
  • Thread.Join Metodu
  • Thread İptal Etme
  • Thread.Interrupt Metodu
Thread Görsel 1

Thread Nedir?

  • Thread, anlam olarak iş parçacığı manasına gelmektedir. Projede ise metotlar gibi program parçacıkları olarak adlandırabiliriz. Bu program parçacıklarının belli başlı görevleri bulunmaktadır. Bu görevler tek seferlik olduğu gibi, uygulama ayakta olduğu sürece de devam edebilir. Bir yazılımın ayağa kalkma sürecinde ilk olarak bir thread oluşturulur. Bu thread’e ana/main thread denir. Ana thread program akışını kontrol eder ve diğer oluşacak veya programcı tarafından oluşturulacak thread’lerin çalışmasını sağlamaktadır. Oluşacak veya programcı tarafından oluşturulacak thread’lere worker thread adı verilmektedir.
  • Thread yapısını anlamak için biraz daha derine inmek gerekmektedir. Bir bilgisayar uygulaması, ayağa kaldırılıp bilgisayar belleğine yüklendiği ve yürütülmeye başlandığında bir process (işlem) haline gelmektedir. Bu process bir veya birden fazla işlemci tarafından işlenebilir. Thread, oluşan process içerisindeki yürütülen talimatlar dizisine denir. Anlam olarak da yukarıda belirttiğim gibi iş parçacığı manasına gelmektedir. Bir thread, CPU’ya gelen talimatların akışlarını yürütebilmek için ihtiyaç duyduğu bütün bilgilere sahiptir ve sahip olmak zorundadır.
  • Küçük bir örnek vermek gerekirse, bir proje yazıyorsunuz ve bir yerde durdunuz. Tekrar dönüp baktığınızda, geri kalanına devam edebilmek için önceki yazdıklarınızın bir yerde kalması gerekmektedir. Aynı şekilde thread de bir iş parçacığını yürütürken yarıda kesip başka bir iş parçasını yürütüp tekrar o işe devam edebilmektedir. Thread’ler, kod akışındaki döngülerden, metotlardan vs. gibi şeylerden etkilenen yazılımsal birimlerdir.

Asenkron ve Senkron Nedir?

  • Senkron ve Asenkron kavramları, programlama açısından işlemlerin zamanlama ve gerçekleşme şekillerini ifade eden kavramlardır. Asenkron; bir işin başka bir işleme bağlı olmadan veya kısmi/zayıf bir şekilde bağlı olduğu durumdur. Senkron; bir işlemin başlaması, kendinden önceki işlemin bitmesine bağlı olduğu durumdur. Senkron kelimesi anlam olarak bağlı, bağımlı manasına gelmektedir. Asenkron kelimesi ise anlam olarak bağımsız manasına gelmektedir.
  • Anlamlardan da yola çıkılacağı üzere, bir işin/kodun senkron olarak ele alınması başka bir işin/kodun bitmesini beklemek gerekmektedir. Aynı şekilde bir işin/kodun asenkron olarak ele alınması, hiçbir işi/kodu beklemeksizin işin/kodun yürütüleceğidir. Asenkron/Senkron ve Multithread kavramları çok karıştırılmaktadır ama teknik olarak birbirinden bağımsız, ayrı kavramlardır. Asenkron veya senkron bir işlem, bir thread üzerinden yürütülebileceği gibi birden fazla thread üzerinden de yürütülebilmektedir.

Asenkron ve Multithread Programlama Nedir?

  • Asenkron programlama, kod akış sürecinde yürütülen işlemlerin birbirinden bağımsız bir şekilde çalıştığı modeldir. Amaç, işin/işlerin yürütüldüğü thread’i bloklamadan devam etmektir. Multithread programlama, kod akışının birden fazla thread üzerinden yürütüldüğü modeldir. Yani bir veya birden fazla işi thread’lere bölerek yürütmektir. Aslında bakıldığında iki programlama da aynı mantıktadır. İkisi de daha az maliyet ile daha yüksek verimlilik gösteren bir yazılım geliştirmektir. Gaye aynı ama farklı programlama tipleridir. Bundan kaynaklı iç içe geçmiş ve karıştırılmaktadır.

Asenkron ve Multithread Programlama Farkları?

Press enter or click to view image in full size
  • Kısaca özetlemek gerekirse, asenkron programlamada amaç ana thread bloklanmadan işlerin yürütülmesi iken, multithread programlamada amaç iş veya işlerin birden fazla thread’e paylaştırılmasıdır.

Thread Sınıfı

  • C# dilinde multithread programlama, bir programın aynı anda birden fazla thread üzerinden yürütülmesini sağlayan programlama türüdür. Thread, bu programlama türündeki programın yürütülmesini sağlayan iş parçacıklarıdır. C# dilinde multithread programlama türünü inşa edebilmek için Thread sınıfından yararlanılır.

Yukarıdaki görselde basit bir thread nasıl oluşturulur bunu örneklemeye çalıştım. Örnekleri mutlaka uygulayın. Tercihim bir konsol uygulamasında örnek kodları uygulamanız.

Thread Id

  • C# dilinde oluşturulan her bir thread için bir id ataması gerçekleşmektedir. Bu id sayesinde yapılan işlerin birbirinden ayırt edilmesi sağlanmaktadır. Bu sayede yapılacak olan trace ve debug işlemleri rahat bir şekilde yürütülmektedir. Kısaca bu id, thread’leri birbirinden ayırmak için kullanılmaktadır.

Yukarıdaki görselde oluşturulan threadlerin Id lerine nasıl erişilebileceğinin yollarını gösterdim.

IsBackground Property

  • Bu property, oluşturulan thread’in arka planda çalışıp çalışmayacağını belirlemektedir. Peki arka planda çalışıp çalışmaması ne gibi fark ortaya koyar? Bir thread’in arka planda çalışması demek, o thread’in main thread’e bağlı olarak çalışması demektir. Eğer arka planda çalışan bir thread ise, main thread bittiği anda o da bitecektir. İşinin bitip bitmemesi önemli değildir. Eğer main thread’e bağlı olmayan bir thread ise, main thread worker thread’in işi bitene kadar programı sonlandırmayacak, onu bekleyecektir.

Görselde IsBackgroundProperty ‘yi örneklendirmeye çalıştım. Kod çalıştıktında sonra görseldeki console çıktısı alınacaktır.

Thread State

  • Programda oluşturulan thread’lerin mevcut durumlarını öğrenmek istenebilir. İşte bu gibi durumlarda ThreadState propertysinden yararlanılmaktadır.

Görselde bir thread ‘in State ‘ini birden fazla state ‘ini gösteren bir örnek yapmaya çalıştım. Bir thread ve thread ’in içinde bir döngü kurdum ve thread ‘i başlattım. Alttaki döngüde de thread sonlanana kadar thread ‘in state ‘ini konsola yazdırdım. Çıktısı da yanındadır.

Race Conditions Nedir? Nasıl Önlemler Alınır?

  • Multithread programlama veya asenkron programlama süreçlerinde genellikle paralel ilerleme gerekmektedir. Bundan kaynaklı da birden fazla thread kullanımı gerekmektedir. Bazı durumlarda bu thread’ler aynı kaynağa (veri, bellek alanı vs.) eş zamanlı olarak erişim sağlamaktadırlar ve bu durum istenmeyen bir durumdur. Örnek vermek gerekirse, birden fazla thread’in aynı anda bir veri üzerinde biri okuma yaparken birinin veriyi değiştirmesi veri tutarsızlığı doğurmaktadır. İşte bu durumların genel olarak adı Race Conditions’dır.
  • Bu duruma çözüm olarak senkron bir yaklaşım izlenmelidir. Bu gibi karşılaşılması muhtemel Race Conditions durumlarında süreci senkron yürütmek ya da tek bir thread üzerinden yürütmek, bu durumu ortadan kaldırmaktadır.

Görselde aynı anda aynı veri üzerinde işlem yapmak isteyen iki thread ‘in oluşturduğu durumu örneklendirmeye çalıştım. Örnek kod parçasını mutlaka deneyerek sizde test edin.

Get Ahmet Faruk Evkaya’s stories in your inbox

Join Medium for free to get updates from this writer.

Yukarıdaki başlıkta Race Conditions nedir onu kısaca anlatmaya çalıştım şimdi de bu durumu nasıl ortadan kaldırabilir o yöntemlerden birine değinmek istiyorum.

Locking Mekanizması

  • Locking mekanizması, birden fazla thread’in eş zamanlı olarak erişmeye çalıştığı alana bir lock koyar. İlk giren thread işini bitirene kadar diğer thread’leri bloklar ve erişim sağlamalarını engeller. Ne zamanki lock ortadan kalkar, o zaman diğer thread’ler yine tek tek girmeye devam eder. Thread’ler arasında bir sıralama mantığı bulunmamaktadır. Lock mekanizması çok hızlı çalışan bir mekanizmadır. Ancak sadece critical section olan bölge için kullanılmalıdır. Aksi takdirde anlamını ve hızını yitirmektedir. Bu yüzden tasarlama, kodlama yapılırken dikkat edilmelidir. Critical Section, birden fazla thread’in eş zamanlı olarak erişmek istediği kaynak/veri bölgesidir.

Görselde bir lock mekanizmasını uygulamaya çalıştım. Öncelikle bir locking tanımladım ve iki thread için bu lock bloğu koydum. Önce hangi thread girer ise o çıkana kadar diğer thread bloklanacak.

Thread.Sleep Metodu

  • Sleep metodu, bir thread’i belirlenen süre boyunca uyutma (duraklatma) için kullanılmaktadır. Belirlenen süre boyunca ilgili thread pasif duruma geçecektir. Süre bittikten sonra tekrar aktif hale gelecektir. Bir best practice olarak ilgili thread’e Thread.Sleep(0) verilmesi tavsiye edilir. Bu da thread’in çalıştığı CPU’yu dinlendirecek, rahatlatacaktır.

Görselde basit bir örnek yapmaya çalıştım. Kodu çalıştırırsanız 1 saniye aralıklar ile konsola yazma işleminin gerçekleştiğini gözlemleyebilirsiniz.

Thread.Join Metodu

  • Bir thread’in başka bir thread’deki işlemin bitmesini gerektiren durumlarda kullanılmaktadır. Bu süre zarfında thread bloklanacaktır. Bu metod sayesinde thread’ler arası senkronizasyon sağlanacaktır. Race Conditions gerektiren durumlarda da kullanılabilmektedir.

Görselde iki thread için join işlemini örneklemeye çalıştım. Konsol çıktısında da göründüğü üzere threadTwo threadOne ‘ın bitmesini beklemektedir. Ondan sonra işlemlerini gerçekleştirmektedir.

Thread İptal Etme

  • Bir thread’i iptal etmek için eskiden Thread.Abort metodu kullanılmaktaydı. Bu metod thread’i aniden sonlandırdığı için thread’in kullandığı kaynakları düzgün bir şekilde temizlememesinden dolayı deprecated edilmiştir. Bu metod yerine artık daha güvenli olan işaretle ve bitir (graceful shutdown) yöntemi kullanılmaktadır. Bu yöntemde belirli bir şart kontrol edilir ve şart sağlanması takdirde thread sonlandırılır.

Görselde thread iptal etme ‘yi örneklendirmeye çalıştım. Thread ‘in sonlanması stop adlı bir değişkene bağlı(graceful shurdown). Stop true olduğu anda thread sonlanacak.

Thread.Interrupt Metodu

  • Bir thread’i bekleyen durumdan uyandırmak ve çalışma durumunu kesintiye uğratmak amacı ile kullanılmaktadır. Burada bekleyen durumdan kasıt, state’i bekleyen durumundadır. Yani thread aslında bir fiil çalışmakta ama state’i beklemede veya uykudadır. Interrupt metodunu kullanırken dikkat edilmesi gerekmektedir. Çünkü uyuyan thread uyandırıldığı zaman ThreadInterruptedException hatası fırlatmaktadır. Bu yüzden try-catch mekanizması kullanılmalıdır. Bu metod genelde bekleme durumunda olan bir thread’i sonlandırmak veya uykuda olan bir metodu işlerine başlaması için tekrar uyandırmak için kullanılır.

Görseldeki kodu çalıştırdığınızda bir hata alacaksınız. Bu yüzden aşağıdaki görseldeki gibi kodlayıp tekrar çalıştırdığınızda konsol çıktısını alırsınız.

Bu yazımın da sonuna gelmiş bulunuyoruz. Bu yazımda Multithread programlamanın temellerini anlatmaya çalıştım. Umarım sizin için güzel ve yararlı bir anlatım olmuştur. Bir sonraki yazımda görüşmek üzere. :)

--

--