10 C Code Examples
Kompilasi 10 program C murni berstandar POSIX (Linux/UNIX/GCC) untuk ujian praktik dan teori OS: System calls manajemen proses, Inter-Process Communication (IPC), Multithreading Pthread, serta penanganan konkurensi (Mutex, Semaphore, dan Algoritma Klasik Sinkronisasi). Seluruh kode valid, compilable, dilengkapi penjelasan per-baris dan expected output.
1. Fork & Process Creation (`fork.c`)
PROCESS MANAGEMENT
Mendemonstrasikan pembuatan proses anak (child process) menggunakan system call fork(). Menunjukkan perbedaan nilai kembalian pid di proses induk (parent) dan anak.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
pid_t pid;
printf("[PARENT] PID utama: %d, bersiap memanggil fork()...\n", getpid());
pid = fork();
if (pid < 0) {
// Fork gagal dialokasikan oleh kernel
perror("Fork gagal dieksekusi");
exit(EXIT_FAILURE);
}
else if (pid == 0) {
// Blok eksekusi proses anak (Child Process)
printf("[CHILD] Halo dari Proses Anak!\n");
printf("[CHILD] PID Anak: %d, Parent PID (PPID): %d\n", getpid(), getppid());
}
else {
// Blok eksekusi proses induk (Parent Process)
printf("[PARENT] Halo dari Proses Induk!\n");
printf("[PARENT] PID Induk: %d, Baru saja melahirkan anak dengan PID: %d\n", getpid(), pid);
}
printf("[ALL] Baris ini dieksekusi oleh kedua proses (PID: %d)\n", getpid());
return 0;
}
🔍 Penjelasan Baris Kunci:
pid = fork();: Kernel menduplikasi PCB, stack, heap, dan deskriptor proses. Setelah baris ini, ada 2 proses konkuren.if (pid == 0): Di proses anak, kernel menyuplai nilai 0 untuk membedakan perannya.else (pid > 0): Di proses parent, kernel menyuplai PID dari anak yang baru dibuat.getpid() & getppid(): Mendapatkan PID diri sendiri dan PID induk.
📟 Expected Terminal Output:
$ gcc -o fork fork_example.c && ./fork [PARENT] PID utama: 4520, bersiap memanggil fork()... [PARENT] Halo dari Proses Induk! [PARENT] PID Induk: 4520, Baru saja melahirkan anak dengan PID: 4521 [ALL] Baris ini dieksekusi oleh kedua proses (PID: 4520) [CHILD] Halo dari Proses Anak! [CHILD] PID Anak: 4521, Parent PID (PPID): 4520 [ALL] Baris ini dieksekusi oleh kedua proses (PID: 4521)
2. Wait & Process Synchronization (`wait.c`)
SYNC & STATUS
Mencegah Zombie Process dengan memanggil wait() di proses orang tua, menahan eksekusi hingga anak tuntas dan mengevaluasi status exit code.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main() {
pid_t pid = fork();
if (pid < 0) {
perror("Fork error");
exit(1);
}
else if (pid == 0) {
printf("[CHILD PID %d] Mulai komputasi berat selama 2 detik...\n", getpid());
sleep(2);
printf("[CHILD] Selesai. Keluar dengan status exit code 42.\n");
exit(42); // Nilai status exit khusus
}
else {
int status;
printf("[PARENT] Menunggu anak (PID %d) selesai dengan wait()...\n", pid);
pid_t child_pid = wait(&status);
printf("[PARENT] Anak (PID %d) telah selesai dieksekusi!\n", child_pid);
if (WIFEXITED(status)) {
printf("[PARENT] Status Exit Code Anak: %d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("[PARENT] Anak terhenti secara paksa oleh sinyal: %d\n", WTERMSIG(status));
}
}
return 0;
}
🔍 Penjelasan Baris Kunci:
wait(&status): Memblokir pemanggil hingga state proses anak berubah. Mengembalikan PID anak yang terminate.WIFEXITED(status): Bernilai true jika proses anak keluar secara normal (misal lewatexit()).WEXITSTATUS(status): Mengekstrak 8-bit terendah dari nilai exit code anak (dalam contoh: 42).
📟 Expected Terminal Output:
$ gcc -o wait wait_example.c && ./wait [PARENT] Menunggu anak (PID 4832) selesai dengan wait()... [CHILD PID 4832] Mulai komputasi berat selama 2 detik... [CHILD] Selesai. Keluar dengan status exit code 42. [PARENT] Anak (PID 4832) telah selesai dieksekusi! [PARENT] Status Exit Code Anak: 42
3. UNIX Anonymous Pipe (IPC) (`pipe.c`)
HALFDUPLEX IPCSaluran komunikasi satu arah (unidirectional) di dalam memori kernel antar-proses berkerabat (Parent-Child) menggunakan 2 file descriptor: read end (fd[0]) dan write end (fd[1]).
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#define BUFFER_SIZE 64
int main() {
int fd[2]; // fd[0] = Read end, fd[1] = Write end
char write_msg[] = "SECRET_PAYLOAD_IPC_0x89A";
char read_msg[BUFFER_SIZE];
// 1. Buat pipa saluran kernel sebelum fork
if (pipe(fd) == -1) {
perror("Pembuatan pipe gagal");
return 1;
}
pid_t pid = fork();
if (pid < 0) {
perror("Fork error");
return 1;
}
else if (pid == 0) {
// CHILD: Bertindak sebagai Writer
close(fd[0]); // Tutup ujung baca yang tidak digunakan
printf("[CHILD] Mengirim data ke pipe: '%s'\n", write_msg);
write(fd[1], write_msg, strlen(write_msg) + 1);
close(fd[1]); // Tutup setelah selesai menulis (kirim EOF)
exit(0);
}
else {
// PARENT: Bertindak sebagai Reader
close(fd[1]); // Tutup ujung tulis yang tidak digunakan
wait(NULL); // Tunggu anak selesai menulis
read(fd[0], read_msg, BUFFER_SIZE);
printf("[PARENT] Menerima data dari pipe: '%s'\n", read_msg);
close(fd[0]); // Tutup ujung baca
}
return 0;
}
🔍 Penjelasan Baris Kunci:
pipe(fd): Mengalokasikan buffer melingkar (circular buffer) di kernel dan mengisi arrayfd[0](read) danfd[1](write).close(fd[0]) / close(fd[1]): Menutup channel yang tidak terpakai sangat penting agar pembaca menerima indikator EOF (End-Of-File) saat writer menutup ujung tulis.
📟 Expected Terminal Output:
$ gcc -o pipe pipe_ipc.c && ./pipe [CHILD] Mengirim data ke pipe: 'SECRET_PAYLOAD_IPC_0x89A' [PARENT] Menerima data dari pipe: 'SECRET_PAYLOAD_IPC_0x89A'
4. POSIX / System V Shared Memory (`shm.c`)
FASTEST IPCMetode IPC tercepat karena dua proses memetakan segmen halaman memori fisik RAM yang sama ke dalam address space virtual mereka, menghindari overhead context switch kernel.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#define SHM_SIZE 1024
int main() {
// 1. Dapatkan identifier unik untuk shared memory segment
key_t key = ftok("/tmp", 65);
int shmid = shmget(key, SHM_SIZE, 0666 | IPC_CREAT);
if (shmid < 0) {
perror("shmget gagal");
exit(1);
}
pid_t pid = fork();
if (pid == 0) {
// CHILD: Attach ke shared memory dan menulis pesan
char *str = (char*) shmat(shmid, (void*)0, 0);
printf("[CHILD] Menulis ke Shared Memory...\n");
strncpy(str, "StudyHub SOC Kernel Shared Memory Buffer v2.0", SHM_SIZE);
shmdt(str); // Detach memori
exit(0);
}
else {
// PARENT: Tunggu anak selesai lalu membaca isi memori
wait(NULL);
char *str = (char*) shmat(shmid, (void*)0, 0);
printf("[PARENT] Membaca dari Shared Memory: '%s'\n", str);
shmdt(str); // Detach memori
// Hancurkan segmen shared memory dari sistem
shmctl(shmid, IPC_RMID, NULL);
}
return 0;
}
🔍 Penjelasan Baris Kunci:
shmget(): Mengalokasikan segmen memori bersama di kernel.shmat(): Memetakan (attach) alamat memori kernel ke virtual pointer di user space.shmdt(): Melepaskan kaitan (detach) segmen dari proses.shmctl(shmid, IPC_RMID, NULL): Menghapus segmen secara permanen agar tidak terjadi memory leak di RAM.
📟 Expected Terminal Output:
$ gcc -o shm shared_memory.c && ./shm [CHILD] Menulis ke Shared Memory... [PARENT] Membaca dari Shared Memory: 'StudyHub SOC Kernel Shared Memory Buffer v2.0'
5. POSIX Thread Creation & Join (`pthread.c`)
MULTITHREADING
Membuat beberapa thread pekerja konkuren menggunakan pustaka standar pthread, melewatkan argumen ID thread, dan menunggu penyelesaiannya lewat pthread_join().
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define NUM_THREADS 3
void* thread_worker(void* arg) {
long tid = (long)arg;
printf("[THREAD %ld] Berjalan aktif di core CPU...\n", tid);
sleep(1);
printf("[THREAD %ld] Tugas komputasi selesai.\n", tid);
pthread_exit((void*)(tid * 100)); // Mengembalikan exit status
}
int main() {
pthread_t threads[NUM_THREADS];
void* status;
printf("[MAIN] Membuat %d worker thread...\n", NUM_THREADS);
for (long i = 0; i < NUM_THREADS; i++) {
int rc = pthread_create(&threads[i], NULL, thread_worker, (void*)i);
if (rc) {
printf("Error pembuatan thread: %d\n", rc);
exit(EXIT_FAILURE);
}
}
// Menunggu setiap thread tuntas (Join)
for (int i = 0; i < NUM_THREADS; i++) {
pthread_join(threads[i], &status);
printf("[MAIN] Thread %d telah bergabung kembali dengan return value: %ld\n", i, (long)status);
}
printf("[MAIN] Seluruh thread sukses dieksekusi!\n");
return 0;
}
🔍 Penjelasan Baris Kunci:
pthread_create(&tid, attr, start_routine, arg): Membuka thread eksekusi baru. Butuh link compiler-lpthread.pthread_join(tid, &retval): Memblokir thread utama sampai thread target selesai, sekaligus mengambil return value-nya.
📟 Expected Terminal Output:
$ gcc -o pthread pthread_example.c -lpthread && ./pthread [MAIN] Membuat 3 worker thread... [THREAD 0] Berjalan aktif di core CPU... [THREAD 1] Berjalan aktif di core CPU... [THREAD 2] Berjalan aktif di core CPU... [THREAD 0] Tugas komputasi selesai. [THREAD 1] Tugas komputasi selesai. [THREAD 2] Tugas komputasi selesai. [MAIN] Thread 0 telah bergabung kembali dengan return value: 0 [MAIN] Thread 1 telah bergabung kembali dengan return value: 100 [MAIN] Thread 2 telah bergabung kembali dengan return value: 200 [MAIN] Seluruh thread sukses dieksekusi!
6. Mutex Lock (Mencegah Race Condition) (`mutex.c`)
MUTUAL EXCLUSION
Mencegah race condition ketika 2 thread serentak memodifikasi variabel penghitung global bersama (shared counter) dengan mengunci critical section menggunakan pthread_mutex_lock.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define ITERATIONS 1000000
long shared_counter = 0;
pthread_mutex_t lock; // Kunci Mutex
void* increment_task(void* arg) {
for (int i = 0; i < ITERATIONS; i++) {
// --- AWAL CRITICAL SECTION ---
pthread_mutex_lock(&lock);
shared_counter++; // Modifikasi aman, eksklusif 1 thread
pthread_mutex_unlock(&lock);
// --- AKHIR CRITICAL SECTION ---
}
return NULL;
}
int main() {
pthread_t t1, t2;
// Inisialisasi Mutex
if (pthread_mutex_init(&lock, NULL) != 0) {
printf("Inisialisasi mutex gagal\n");
return 1;
}
pthread_create(&t1, NULL, increment_task, NULL);
pthread_create(&t2, NULL, increment_task, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_mutex_destroy(&lock);
printf("Ekspektasi Counter : %d\n", ITERATIONS * 2);
printf("Hasil Riil Counter : %ld\n", shared_counter);
if (shared_counter == ITERATIONS * 2) {
printf("✅ SUKSES: Tidak terjadi Race Condition berkat Mutex!\n");
} else {
printf("❌ GAGAL: Terjadi Data Corruption Race Condition!\n");
}
return 0;
}
🔍 Penjelasan Baris Kunci:
pthread_mutex_lock(&lock): Thread meminta kunci. Jika kunci sedang dipegang thread lain, thread pemanggil diblokir tidur (sleep).pthread_mutex_unlock(&lock): Melepas kunci dan membangunkan thread lain di antrean.- Tanpa mutex, operasi
shared_counter++yang terdiri dari 3 instruksi assembly (MOV, ADD, MOV) akan saling menimpa secara acak (data corruption).
📟 Expected Terminal Output:
$ gcc -o mutex mutex_counter.c -lpthread && ./mutex Ekspektasi Counter : 2000000 Hasil Riil Counter : 2000000 ✅ SUKSES: Tidak terjadi Race Condition berkat Mutex!
7. POSIX Counting Semaphore (`semaphore.c`)
RESOURCE COUNTING
Mengontrol akses terbatas terhadap kolam sumber daya (Resource Pool) yang hanya berkapasitas 2 slot serentak menggunakan sem_init, sem_wait, dan sem_post.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#define TOTAL_CLIENTS 5
#define MAX_CONCURRENT_SLOTS 2 // Hanya 2 thread boleh masuk bersamaan
sem_t slot_semaphore;
void* client_access(void* arg) {
long id = (long)arg;
printf("[CLIENT %ld] Mengantre menunggu izin slot...\n", id);
// Operasi wait(S) / P(S): Mengurangi counter semaphore
sem_wait(&slot_semaphore);
printf("--> [CLIENT %ld] MENDAPATKAN SLOT! Sedang memakai layanan...\n", id);
sleep(2); // Simulasi pemrosesan
printf("<-- [CLIENT %ld] Selesai memakai. Melepaskan slot.\n", id);
// Operasi signal(S) / V(S): Menaikkan counter semaphore
sem_post(&slot_semaphore);
return NULL;
}
int main() {
pthread_t clients[TOTAL_CLIENTS];
// Inisialisasi semaphore dengan nilai awal 2
sem_init(&slot_semaphore, 0, MAX_CONCURRENT_SLOTS);
for (long i = 0; i < TOTAL_CLIENTS; i++) {
pthread_create(&clients[i], NULL, client_access, (void*)i);
}
for (int i = 0; i < TOTAL_CLIENTS; i++) {
pthread_join(clients[i], NULL);
}
sem_destroy(&slot_semaphore);
printf("[MAIN] Seluruh client selesai dilayani dengan tertib.\n");
return 0;
}
🔍 Penjelasan Baris Kunci:
sem_init(&sem, 0, 2): Argumen kedua bernilai 0 berarti semaphore dibagi antar-thread dalam satu proses (bukan antar-proses). Argumen ketiga adalah kapasitas awal (2).sem_wait(): Mengurangi slot. Jika slot bernilai 0, thread tertahan tidur.sem_post(): Menambah slot dan membangunkan salah satu thread yang tertidur.
📟 Expected Terminal Output:
$ gcc -o sem semaphore_pool.c -lpthread && ./sem [CLIENT 0] Mengantre menunggu izin slot... --> [CLIENT 0] MENDAPATKAN SLOT! Sedang memakai layanan... [CLIENT 1] Mengantre menunggu izin slot... --> [CLIENT 1] MENDAPATKAN SLOT! Sedang memakai layanan... [CLIENT 2] Mengantre menunggu izin slot... <-- [CLIENT 0] Selesai memakai. Melepaskan slot. --> [CLIENT 2] MENDAPATKAN SLOT! Sedang memakai layanan...
8. Producer-Consumer (Bounded Buffer) (`prod_cons.c`)
CLASSIC IPC CONCURRENCY
Solusi masalah klasik Bounded Buffer dengan 2 Semaphore (empty dan full) serta 1 Mutex untuk mencegah overflow dan underflow pada buffer berukuran tetap.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#define BUFFER_SIZE 4
#define TOTAL_ITEMS 8
int buffer[BUFFER_SIZE];
int in = 0, out = 0;
sem_t sem_empty; // Menghitung ruang buffer kosong
sem_t sem_full; // Menghitung jumlah item yang siap dibaca
pthread_mutex_t buffer_mutex;
void* producer(void* arg) {
for (int i = 1; i <= TOTAL_ITEMS; i++) {
sem_wait(&sem_empty); // Tunggu sampai ada ruang kosong
pthread_mutex_lock(&buffer_mutex);
buffer[in] = i * 10;
printf("[PRODUCER] Menaruh item %d di slot buffer [%d]\n", buffer[in], in);
in = (in + 1) % BUFFER_SIZE;
pthread_mutex_unlock(&buffer_mutex);
sem_post(&sem_full); // Kabarkan ada item baru
usleep(100000); // Istirahat 100ms
}
return NULL;
}
void* consumer(void* arg) {
for (int i = 1; i <= TOTAL_ITEMS; i++) {
sem_wait(&sem_full); // Tunggu sampai ada item
pthread_mutex_lock(&buffer_mutex);
int item = buffer[out];
printf(" [CONSUMER] Mengambil item %d dari slot [%d]\n", item, out);
out = (out + 1) % BUFFER_SIZE;
pthread_mutex_unlock(&buffer_mutex);
sem_post(&sem_empty); // Kabarkan ada ruang kosong
usleep(250000); // Consumer sedikit lebih lambat
}
return NULL;
}
int main() {
pthread_t prod_thread, cons_thread;
sem_init(&sem_empty, 0, BUFFER_SIZE); // Awal: semua 4 slot kosong
sem_init(&sem_full, 0, 0); // Awal: 0 item
pthread_mutex_init(&buffer_mutex, NULL);
pthread_create(&prod_thread, NULL, producer, NULL);
pthread_create(&cons_thread, NULL, consumer, NULL);
pthread_join(prod_thread, NULL);
pthread_join(cons_thread, NULL);
sem_destroy(&sem_empty);
sem_destroy(&sem_full);
pthread_mutex_destroy(&buffer_mutex);
return 0;
}
🔍 Penjelasan Baris Kunci:
sem_empty: Bernilai 4 saat awal. Jika buffer penuh (0 slot kosong), producer terblokir.sem_full: Bernilai 0 saat awal. Jika buffer kosong, consumer tertidur menunggu producer.in = (in + 1) % BUFFER_SIZE: Pointer circular buffer untuk operasi efisien antrean FIFO.
📟 Expected Terminal Output:
$ gcc -o prod_cons producer_consumer.c -lpthread && ./prod_cons
[PRODUCER] Menaruh item 10 di slot buffer [0]
[CONSUMER] Mengambil item 10 dari slot [0]
[PRODUCER] Menaruh item 20 di slot buffer [1]
[PRODUCER] Menaruh item 30 di slot buffer [2]
[CONSUMER] Mengambil item 20 dari slot [1]
9. Readers-Writers Problem (`readers_writers.c`)
DATABASE ACCESS SYNCSinkronisasi akses dataset: Multiple Readers diizinkan membaca serentak, namun saat Writer masuk, seluruh proses lain dicegah masuk (eksklusif murni).
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t rw_mutex; // Kunci eksklusif untuk Penulis / Writer
pthread_mutex_t count_mutex; // Kunci untuk memproteksi variabel reader_count
int reader_count = 0;
int database_data = 100;
void* reader(void* arg) {
long id = (long)arg;
// Masuk reader
pthread_mutex_lock(&count_mutex);
reader_count++;
if (reader_count == 1) {
// Reader pertama mengunci penulis agar tidak bisa menulis saat membaca
pthread_mutex_lock(&rw_mutex);
}
pthread_mutex_unlock(&count_mutex);
// --- MEMBACA DATABASE BERSAMA ---
printf(" [READER %ld] Membaca data bernilai: %d (Total Reader Aktif: %d)\n", id, database_data, reader_count);
usleep(150000);
// Keluar reader
pthread_mutex_lock(&count_mutex);
reader_count--;
if (reader_count == 0) {
// Reader terakhir melepaskan kunci penulis
pthread_mutex_unlock(&rw_mutex);
}
pthread_mutex_unlock(&count_mutex);
return NULL;
}
void* writer(void* arg) {
long id = (long)arg;
pthread_mutex_lock(&rw_mutex); // Kunci seluruh akses!
database_data += 50;
printf("--> [WRITER %ld] Mengubah nilai data menjadi: %d (EKSKLUSIF)\n", id, database_data);
usleep(200000);
pthread_mutex_unlock(&rw_mutex);
return NULL;
}
int main() {
pthread_t r[4], w[2];
pthread_mutex_init(&rw_mutex, NULL);
pthread_mutex_init(&count_mutex, NULL);
pthread_create(&r[0], NULL, reader, (void*)1);
pthread_create(&w[0], NULL, writer, (void*)1);
pthread_create(&r[1], NULL, reader, (void*)2);
pthread_create(&r[2], NULL, reader, (void*)3);
pthread_create(&w[1], NULL, writer, (void*)2);
pthread_create(&r[3], NULL, reader, (void*)4);
for (int i = 0; i < 4; i++) pthread_join(r[i], NULL);
for (int i = 0; i < 2; i++) pthread_join(w[i], NULL);
pthread_mutex_destroy(&rw_mutex);
pthread_mutex_destroy(&count_mutex);
return 0;
}
🔍 Penjelasan Baris Kunci:
if (reader_count == 1) pthread_mutex_lock(&rw_mutex): Reader pertama menyalakan gembok untuk seluruh kawanan pembaca berikutnya.if (reader_count == 0) pthread_mutex_unlock(&rw_mutex): Hanya saat pembaca terakhir keluar, pintu dibuka kembali untuk Penulis (Writer).
📟 Expected Terminal Output:
$ gcc -o rw readers_writers.c -lpthread && ./rw [READER 1] Membaca data bernilai: 100 (Total Reader Aktif: 1) --> [WRITER 1] Mengubah nilai data menjadi: 150 (EKSKLUSIF) [READER 2] Membaca data bernilai: 150 (Total Reader Aktif: 2) [READER 3] Membaca data bernilai: 150 (Total Reader Aktif: 2) --> [WRITER 2] Mengubah nilai data menjadi: 200 (EKSKLUSIF)
10. Dining Philosophers (Pencegahan Deadlock) (`philosophers.c`)
DEADLOCK PREVENTIONImplementasi masalah 5 Filsuf makan menggunakan strategi Resource Ordering (filsuf bernomor ganjil mengambil sumpit kanan terlebih dahulu) guna mematahkan kondisi Circular Wait secara matematis.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define NUM_PHILOSOPHERS 5
pthread_mutex_t chopsticks[NUM_PHILOSOPHERS];
void* philosopher(void* arg) {
long id = (long)arg;
int left_fork = id;
int right_fork = (id + 1) % NUM_PHILOSOPHERS;
// Berpikir sejenak
printf("[FILSUF %ld] Sedang merenung dan berpikir...\n", id);
usleep(100000);
// STRATEGI PENCEGAHAN DEADLOCK:
// Filsuf bernomor ganjil mengambil kanan dulu; genap mengambil kiri dulu
if (id % 2 == 0) {
pthread_mutex_lock(&chopsticks[left_fork]);
pthread_mutex_lock(&chopsticks[right_fork]);
} else {
pthread_mutex_lock(&chopsticks[right_fork]);
pthread_mutex_lock(&chopsticks[left_fork]);
}
// --- SESI MAKAN ---
printf("🍝 [FILSUF %ld] Sedang makan lezat dengan sumpit (%d & %d)!\n", id, left_fork, right_fork);
usleep(200000);
// Melepaskan sumpit
pthread_mutex_unlock(&chopsticks[left_fork]);
pthread_mutex_unlock(&chopsticks[right_fork]);
printf("[FILSUF %ld] Selesai makan, meletakkan kedua sumpit.\n", id);
return NULL;
}
int main() {
pthread_t phils[NUM_PHILOSOPHERS];
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
pthread_mutex_init(&chopsticks[i], NULL);
}
for (long i = 0; i < NUM_PHILOSOPHERS; i++) {
pthread_create(&phils[i], NULL, philosopher, (void*)i);
}
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
pthread_join(phils[i], NULL);
}
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
pthread_mutex_destroy(&chopsticks[i]);
}
printf("✅ SUKSES: Seluruh 5 filsuf selesai makan tanpa terjebak Deadlock!\n");
return 0;
}
🔍 Penjelasan Baris Kunci:
- Jika semua filsuf mengambil sumpit kiri secara serempak, timbul Circular Wait di mana masing-masing menahan 1 sumpit dan menunggu sumpit kanan tetangga (Deadlock total).
- Dengan membuat filsuf ganjil mengambil sumpit berurutan sebaliknya (kanan dulu baru kiri), rantai sirkular terputus dan minimal satu filsuf dipastikan berhasil meraih 2 sumpit sekaligus untuk makan.
📟 Expected Terminal Output:
$ gcc -o phils dining_philosophers.c -lpthread && ./phils [FILSUF 0] Sedang merenung dan berpikir... [FILSUF 1] Sedang merenung dan berpikir... 🍝 [FILSUF 0] Sedang makan lezat dengan sumpit (0 & 1)! 🍝 [FILSUF 2] Sedang makan lezat dengan sumpit (2 & 3)! [FILSUF 0] Selesai makan, meletakkan kedua sumpit. 🍝 [FILSUF 1] Sedang makan lezat dengan sumpit (1 & 2)! ✅ SUKSES: Seluruh 5 filsuf selesai makan tanpa terjebak Deadlock!