42 Philosophers Projesi

Eren Erdoğan
4 min readJan 31, 2023

--

42 Philosophers projesi, aşağıdakileri içerir:

  • Bir masada birkaç filozof oturur. Her filozof için bir tabak yemek ve bir çatal bulunur.
  • Her filozof, yemek yemek için iki çatala ihtiyaç duyar.
  • Bir filozof yemek yemek istediğinde, sağ ve sol çatalı almaya çalışır. Eğer iki çatal da mevcutsa, o filozof yemek yer ve çatalları masaya bırakır. Eğer biri veya ikisi de kullanımda ise, o filozof bekler ve sonra tekrar dener.
  • Bu süreç, her hangi bir filozof açlıktan ölene kadar devam eder.

Bilinmesi Gerekenler

Bu projeyi yapabilmek için thread ve mutex kavramlarını bilmek gereklidir.

C dilinde, thread ve mutex, bir işlemi birden fazla parçaya ayırma ve bu parçaları aynı anda çalıştırma işlemine denir. Thread, bir işlemi birden fazla parçaya ayırır ve bu parçaları aynı anda çalıştırır, böylece işlem daha hızlı tamamlanır. Mutex ise, bir işlem sırasında kullanılan kaynakların diğer işlemler tarafından kullanılmamasını sağlar. Böylece, bir işlem sırasında bir kaynağın birden fazla işlem tarafından aynı anda kullanılması ve bu kaynakta oluşabilecek çakışmaların önüne geçilir.

#include <pthread.h>
#include <stdio.h>
// Thread işlevi
void *myThreadFun(void *vargp)
{
printf("Bu bir thread örneğidir.\n");
return NULL;
}
int main()
{
pthread_t thread_id;
printf("Ana işlem başlıyor.\n");
// Thread oluşturma
pthread_create(&thread_id, NULL, myThreadFun, NULL);
// Thread'in tamamlanmasını bekleme
pthread_join(thread_id, NULL);
printf("Ana işlem bitti.\n");
return 0;
}

Bu örnek kodda, pthread_create() fonksiyonu ile bir thread oluşturulur ve pthread_join() fonksiyonu ile bu thread’in tamamlanması beklenir. Thread işlevi ise myThreadFun() fonksiyonudur.

Bir mutex örneği ise aşağıdaki gibidir

#include <pthread.h>
#include <stdio.h>
// Global değişken
int x = 0;
// Mutex nesnesi
pthread_mutex_t mutex;
// Thread işlevi
void *myThreadFun(void *vargp)
{
// Mutex kilidini alma
pthread_mutex_lock(&mutex);
// Kritik bölge: x değerini 1 arttırma
x++;
// Mutex kilidini serbest bırakma
pthread_mutex_unlock(&mutex);
return NULL;
}
int main()
{
pthread_t thread_id1, thread_id2;
// Mutex nesnesini başlatma
pthread_mutex_init(&mutex, NULL);
// İlk thread'i oluşturma ve çalıştırma
pthread_create(&thread_id1, NULL, myThreadFun, NULL);
// İkinci thread'i oluşturma ve çalıştırma
pthread_create(&thread_id2, NULL, myThreadFun, NULL);
// Thread'lerin tamamlanmasını bekleme
pthread_join(thread_id1, NULL);
pthread_join(thread_id2, NULL);
// Mutex nesnesini sonlandırma
pthread_mutex_destroy(&mutex);
printf("x değeri: %d\n", x);
return 0;
}

Bu kodda, pthread_mutex_init() fonksiyonu ile bir mutex nesnesi oluşturulur ve `pthread_mutex_lock() ve pthread_mutex_unlock() fonksiyonları ile bu nesnenin kilidi alınıp serbest bırakılır. Böylece,myThreadFun() fonksiyonu içinde bulunan kritik bölge (x++satırı) tek bir thread tarafından bir kez kullanılabilir ve diğer thread’ler bu kritik bölgeye erişemez. Bu sayede,x` değişkeninin birden fazla thread tarafından aynı anda değiştirilmesi ve bu değişkenin doğru değerini kaybetmesi engellenmiş olur.

pthread_create() fonksiyonu, bir thread oluşturmak için kullanılır. Bu fonksiyonun argümanları şunlardır:

  1. pthread_t *thread: Oluşturulacak thread’in tanımlanacağı değişkenin adresidir. Bu değişken, daha sonra thread’in özelliklerini ve durumunu tutacaktır.
  2. const pthread_attr_t *attr: Oluşturulacak thread’in özelliklerini belirleyen bir değerdir. Bu argüman genellikle NULL olarak verilir ve varsayılan özellikler kullanılır.
  3. void *(*start_routine) (void *): Oluşturulacak thread’in işlevini belirleyen fonksiyonun adresidir. Bu fonksiyon, void * tipinde bir argüman alır ve void * tipinde bir değer döndürür.
  4. void *arg: start_routine fonksiyonuna geçirilecek argümanı belirleyen değerdir. Bu argüman start_routine fonksiyonuna geçirilerek işlev içinde kullanılabilir.
pthread_t thread_id;
int thread_num = 1;
// Thread oluşturma
pthread_create(&thread_id, NULL, myThreadFun, &thread_num);

Bu kodda, pthread_create() fonksiyonuna thread_id değişkeni (1. argüman), NULL değeri (2. argüman) ve myThreadFun fonksiyonunun adresi (3. argüman) verilmiştir. Dördüncü argüman olarak da, thread_num değişkeninin adresi verilmiştir. Bu değişken, myThreadFun işlevi içinde void *vargp argümanı olarak kullanılacaktır.

./philo

1 number_of_philosophers

2 time_to_die

3 time_to_eat

4 time_to_sleep

5 number_of_times_each_philosopher_must_eat (isteğe bağlı)

gettimeofday() fonksiyonu, UNIX benzeri işletim sistemlerinde sistem saatini döndürür. Bu fonksiyon, sys/time.h kütüphanesinde bulunur ve aşağıdaki iki argümanı alır

  1. struct timeval *tv: Bu argüman, sistem saatini tutan bir yapıdır. Bu yapının tv_sec ve tv_usec öğeleri sistem saatini saniye ve mikrosaniye cinsinden tutar.
  2. struct timezone *tz: Bu argüman, saat dilimini tutan bir yapıdır. Bu yapının tz_minuteswest ve tz_dsttime öğeleri saat dilimini dakika cinsinden ve yaz saati uygulamasını belirtir.

gettimeofday() fonksiyonu, sistem saatini döndürür ve bu saati tv yapısına atar. Örneğin, aşağıdaki kod parçasında gettimeofday() fonksiyonu kullanılmıştır:

#include <stdio.h>
#include <sys/time.h>
int main()
{
struct timeval tv;
gettimeofday(&tv, NULL);
printf("Sistem saati: %ld s %ld us\n", tv.tv_sec, tv.tv_usec);
return 0;
}

Bu kodda, gettimeofday() fonksiyonu ile sistem saati alınmış ve tv yapısına atanmıştır. Daha sonra, tv.tv_sec ve tv.tv_usec öğeleri kullanarak sistem saatini saniye ve mikrosaniye cinsinden ekrana yazdırılmıştır. Bu sayede, gettimeofday() fonksiyonu ile sistem saati alınıp kullanılmıştır.

usleep() fonksiyonu, bir Unix sisteminde bir iş parçacığının belirli bir miktar süre beklemesini sağlar. Bu fonksiyon, aşağıdaki argümanı alır:

  • useconds_t usec: Bu argüman, iş parçacığının kaç mikrosaniye boyunca bekleyeceğini belirtir.
#include <unistd.h>
#include <stdio.h>
int main()
{
printf("Waiting for 3 seconds…\n");
usleep(3000000);
printf("Done waiting!\n");
return 0;
}
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>

int main() {
struct timeval tv1;
struct timeval tv2;
long long time1, time2;
gettimeofday(&tv1, NULL);
usleep(3000000);
gettimeofday(&tv2, NULL);
time1 = tv1.tv_sec * 1000 + tv1.tv_usec / 1000;
time2 = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;
printf("%lld\n", time1);
printf("%lld\n", time2);
printf("%lld\n", time2 - time1);
return 0;
}

Github : https://github.com/codewitheren/philosophers_42_Turkey

--

--