thread etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
thread etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
 Aynı anda birden fazla thread'in çalıştığı sistemlerde, thread'lerin birbirleriyle haberleşmesi, senkron bir şekilde çalışması gerekebilir. Bu yazımızda C programlama dilinde thread'lerin mutex'ler ile nasıl senkronizasyonu yapılacağını inceleyeceğiz.


Thread Senkronizasyonu Nedir

Thread senkronizasyonu, iki veya daha fazla eşzamanlı işlemin veya thread'in kritik bölümü olarak bilinen program segmentini aynı anda yürütmemesini sağlayan bir mekanizma olarak tanımlanır. Senkranizaasyon teknikleri kullanılarak süreçlerin kritik bölüme erişimi kontrol edilir. Bir thread'in kritik bölümü yürütülmeye başladığı anda, diğer thread ilk thread'in işi bitene kadar bekler. Uygun senkronizasyon teknikleri uygulanmaz ise, değişkenlerin değerlerinin tahmin edilemeyen ve proseslerin veya thread'lerin context switch ( bağlam anahtarı) zamanlamasına bağlı olarak değişebileceği bir yarış durumuna neden olabilir.


Mutex ile Senkronizasyon

Mutex ile paylaşılan bir kaynağı kilitler, sonrada serbest bırakırız. Kilitlenen kod bölgesi serbest bırakılana kadar başka hiçbir thread erişemez. 

pthread_mutex_t mutex; ile mutex adında bir nesne oluşturulur. 

pthread_mutex_init(&mutex,0); ile  mutex oluşturulur. Başarılı bir şekilde mutex oluşturulursa 0 döndürür, başarılı bir şekilde mutex oluşturulmaz ile -1 döndürür.

pthread_mutex_destroy(&mutex); ile tanımlayan mutex nesnesini siler. Mutex'ler paylaşılan kaynakları korumak için kullanılırlar. Başarılıysa 0, değilse -1 döner.

pthread_mutex_lock(&mutex); ile tanımlanan mutex nesnesini kilitler(lock). Mutex zaten başka bir thread tarafından kilitlenmiş ise, thread mutex'in kullanılabilir olmasını bekler. Bir mutex'i kilitleyen thread, mevcut sahibi olur ve aynı thread onu açana kadar sahibi olarak kalır. Başarılıysa 0, değilse -1 döner.

pthread_mutex_unlock(&mutex); ile mutex nesnesi serbest bırakılır. Başarılıysa 0, değilse -1 döner.

pthread_self(); ise bulunduğu thread'in ID numarasını elde etmemizi sağlar.


Şimdi bir örnek yapalım:




Örneğimizde aynı yere ulaşmaya çalışan 5 tane thread vardır. Bu 5 thread aynı hafıza bölgesine erişmeye çalışmaktadır. Aralarında bir yarış durumu olmaması için senkronizasyon yaptık. Önce pthread_mutex_t mutex; ile bir mutex nesnesi oluşturduk. Daha sonra main() içerisinde pthread_mutex_init() ile mutex'imizi oluşturduk. pthread_mutex_destroy() ile oluşturduğumuz mutex'i siliyoruz. Yani main() içerisinde mutex oluşturuyoruz ve siliyoruz. void *thread() içinde pthread_mutex_lock() ile kilitlemek istediğimiz kod bloğunun üzerine yazdık. Buradan sonrası pthread_mutex_unlock() yazılana kadar kilitli olan blok olacaktır. pthread_mutex_unlock() ile kilitlenen kod bloğunu serbest bırakılır.



Ekran Çıktısı:






Kaynaklar:

https://www.geeksforgeeks.org/mutex-lock-for-linux-thread-synchronization/
https://www.bogotobogo.com/cplusplus/multithreading_pthread.php

 Thread Nedir?

Bir thread, bir process içerisindeki yürütme birimidir. Bir process'in aynı anda birden fazla işi yapmasını sağlayan yapılardır. Bir process, yapısında birden fazla thread bulundurabilir, bu yapılara multithreading denir. 

Process Nedir?

Process, ihtiyaç duyulan tüm kaynaklar ile birlikte belleğe yüklenmiş bir programdır. Her process'in ihtiyaç duyduğu temel kaynaklar; register, counter ve stack'tir. Her processin ayrı bir bellek adresi vardır, bu da her işlemin bağımsız olarak çalıştığı ve diğer işlemlerden izole edildiği anlamına gelir. Yani bir process çalışırken yalnızca kendini çalışıyor zanneder. Diğer işlemlerde paylaşılan verilere doğrudan erişemez.

Process vs Thread

  • Bir thread’in oluşturulması ve sonlandırılması process’lere göre daha kısa sürer
  • Process’ler birbirinden izole bir şekilde çalışırken, thread’ler aynı bellek kaynağını paylaşır
  • Process’ler, thread’lere göre daha fazla kaynak tüketimi yaparlar
  • Bir process bloklanırsa başka bir process işlemini gerçekleştiremez. Öncelikle ilk process’in işini bitirmesini bekler. Ancak bu durum thread’lerde geçerli değildir. Bir thread başka bir thread bloklansa bile çalışabilir.
  • Ölçeklenebilirlik açısından thread’ler daha avantajlıdır. Process’lerin ölçeklendirilmesi için çok işlemcili yapı gerekmektedir. Bu da processler’de ölçeklendirmenin donanımsal olarak yapıldığını bizlere gösteriyor. thread’lerde ise çok çekirdekli işlemcilerde birden fazla thread farklı çekirdeklerde çalıştırılabilir.

C Programlamada Thread Oluşturma

Linux işletim sistemini kullanarak thread'leri kolaylıkla oluşturabiliriz. Şimdi ilk örneğe bakalım:

#include <pthread.h>

#include <stdio.h>

#include <stdlib.h>

void *worker_thread(void *arg)

{

        printf("This is worker_thread()\n");

        return NULL;

}

int main()

{

        pthread_t my_thread;

        int ret;

        printf("In main: creating thread\n");

        ret = pthread_create(&my_thread, NULL, &worker_thread, NULL);

   if(ret != 0) {

                printf("Error: pthread_create() failed\n");

        }

        pthread_join(my_thread, NULL);

        return 0;

}
Çıktı:



Main thread, worker_thread yürütmek için bir thread oluşturacaktır. Main de pthread_t türünde my_thread adında bir değişken bildirdik. Bir thread oluşturmak için pthread_create() fonksiyonunu kullandık. Bu fonksiyon 4 tane değişken alır. Bunlar:
  • İlki, my_thread için bir pointer,
  • İkincisi, nitelikleri belirtir,
  • Üçüncüsü, thread için yürütülecek olan fonksiyon,
  • Dördüncüsü, worker_thread fonksiyonuna argüman göndermek için kullanılır.
pthread_join fonksiyonu ile, bir thread'in sonlanmasını bekleyebiliriz. Bu fonksiyonun kullanıldığı thread, sonlanması beklenen thread sonlanana kadar bloklanacaktır.

Başka bir örnek daha, bu örnekte 5 tane thread oluşturduk:

 

#include <pthread.h>

#include <stdio.h>

#include <stdlib.h>

#define N 5

void *worker_thread(void *arg)

{

        printf("This is worker_thread #%ld\n", (long)arg);

        return NULL;

}

int main()

{

        pthread_t my_thread[N];

        long id;

   int ret;

        printf("In main: creating thread\n");

        for(id = 1; id <= N; id++) {

                ret =  pthread_create(&my_thread[id], NULL, worker_thread, (void*)id);

                if(ret != 0) {

                        printf("Error: pthread_create() failed\n");

                }

        }

        for(id = 1; id <= N; id++) {

pthread_join(my_thread[id], NULL);

  }

        return 0;

}


Çıktı:





Kaynaklar:

http://alpegeakarsu.com/process-ve-thread-nedir/

https://demirten.gitbooks.io/linux-sistem-programlama/content/threads/types.html

https://devnot.com/2021/thread-nedir-detayli-bir-thread-incelemesi/

https://www.elektrikport.com/teknik-kutuphane/thread-nedir-thread-cde-nasil-kullanilir-ve-nasil-yazilir/23510#ad-image-0