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