C'de Mutex ve Semaphore ile Thread Senkronizasyonu

Birden fazla thread aynı kaynağa eriştiğinde veri bozulması kaçınılmazdır. Mutex ve Semaphore bu sorunu çözen iki temel mekanizmadır.

Mutex (mutual exclusion) kritik bölüme bir seferde yalnızca bir thread'in girmesini sağlar. Semaphore ise sayaç tabanlıdır, belirli sayıda thread'in kaynağa erişmesine izin verir. Binary semaphore mutex gibi davranırken, counting semaphore havuz yönetiminde kullanışlıdır.

Pratik bir örnek: iki thread'in aynı sayacı artırması. Senkronizasyon olmadan sonuç yanlış çıkar.

1 <stdio.h>
2 <pthread.h>
3 <semaphore.h>
4 <unistd.h>
5
6int counter = 0;
7sem_t sem;
8
9void* increment_counter(void* arg) {
10for (int i = 0; i < 1000000; i++) {
11sem_wait(&sem); // Kritik bölüme gir
12counter++;
13sem_post(&sem); // Kritik bölümden çık
14}
15return NULL;
16}
17
18int main() {
19pthread_t t1, t2;
20
21sem_init(&sem, 0, 1); // Binary semaphore (1 = açık)
22
23pthread_create(&t1, NULL, increment_counter, NULL);
24pthread_create(&t2, NULL, increment_counter, NULL);
25
26pthread_join(t1, NULL);
27pthread_join(t2, NULL);
28
29printf("Counter: %d (beklenen: 2000000)\n", counter);
30sem_destroy(&sem);
31
32return 0;
33}

Derle ve çalıştır:

1gcc -pthread -o sync sync.c./sync

Beklenen çıktı: `Counter: 2000000`

Reklam · TEST
AdSense Test ReklamıYazı arası (gönderi içi) · Yazı arası

Semaphore olmadan çalıştırırsan sonuç her defasında farklı çıkar, race condition nedeniyle. `sem_wait()` sayacı 1 azaltıp beklerse, `sem_post()` onu 1 artırır. Sayaç 0 olunca diğer thread'ler bekler.

Mutex ile aynı işlem:

1pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
2
3void* increment_with_mutex(void* arg) {
4for (int i = 0; i < 1000000; i++) {
5pthread_mutex_lock(&lock);
6counter++;
7pthread_mutex_unlock(&lock);
8}
9return NULL;
10}

Mutex daha basit ve okunması kolay. Semaphore ise birden fazla kaynağı yönetmek için tercih edilir, örneğin havuzda 3 bağlantı varsa `sem_init(&sem, 0, 3)` ile başla.

Sık hata: `sem_wait()` çağrısından sonra exception fırlatılırsa `sem_post()` asla çalışmaz ve deadlock oluşur. Bu yüzden C++'da `lock_guard` veya Rust'ta ownership mekanizması tercih edilir. C'de güvenli olmak için try-catch yerine `goto cleanup` deseni kullan.

Reklam · TEST
AdSense Test ReklamıGönderi altı · Görüntülü
konu hakkında tepkinizi verebilirsiniz