Back to IF3130 Sistem Paralel dan Terdistribusi

Topic

Questions/Cues

  • Apa keterbatasan Mutex?

  • Apa itu masalah Produsen-Konsumen?

  • Apa itu Semaphore?

  • Bagaimana cara kerja Semaphore?

  • Fungsi-fungsi untuk Semaphore?

  • Beda utama Mutex & Semaphore?

Reference Points

  • Slide “paralel programming model: shared memory” (Hal. 42-46)

Keterbatasan Mutex: Masalah Urutan

Mutex sangat baik untuk menjamin hanya satu thread yang masuk ke critical section pada satu waktu (eksklusi mutual). Namun, Mutex tidak peduli dengan urutan thread mana yang akan masuk berikutnya. Sistem operasi yang akan menentukannya. Ada kalanya kita butuh kontrol yang lebih dari itu, di mana sebuah thread harus menunggu sinyal dari thread lain sebelum bisa melanjutkan.

Masalah Klasik: Produsen-Konsumen (Producer-Consumer)

Ini adalah pola umum dalam pemrograman di mana satu atau lebih thread (produsen) menghasilkan data dan meletakkannya di sebuah buffer (antrean/wadah bersama), sementara satu atau lebih thread lain (konsumen) mengambil dan memproses data dari buffer tersebut.

Analogi: Bayangkan sebuah ban berjalan di pabrik. Produsen menaruh barang di ban berjalan, dan konsumen mengambilnya di ujung lain. Masalahnya:

  1. Produsen tidak boleh menaruh barang jika ban berjalan sudah penuh. Ia harus menunggu sampai ada ruang kosong.

  2. Konsumen tidak boleh mengambil barang jika ban berjalan kosong. Ia harus menunggu sampai ada barang yang ditaruh.

Mutex saja tidak cukup untuk menyelesaikan ini, karena kita perlu “menghitung” jumlah barang dan ruang kosong, serta memberi sinyal antar thread.

Semaphore: Mutex yang Bisa Berhitung

Semaphore adalah sebuah primitive sinkronisasi yang lebih umum daripada mutex. Ia pada dasarnya adalah sebuah penghitung (counter) integer non-negatif yang operasinya dijamin atomic (tidak bisa diinterupsi). Semaphore digunakan untuk mengontrol akses ke sekumpulan sumber daya.

Mekanisme Kerja Semaphore

Semaphore bekerja melalui dua operasi utama:

  1. sem_wait() (juga dikenal sebagai P, wait, atau down):

    • Mencoba mengurangi nilai semaphore sebanyak 1.

    • Jika nilai semaphore > 0, operasi berhasil dan thread lanjut berjalan.

    • Jika nilai semaphore == 0, thread akan diblokir (tidur) sampai ada thread lain yang menaikkan nilainya.

  2. sem_post() (juga dikenal sebagai V, signal, atau up):

    • Menaikkan nilai semaphore sebanyak 1.

    • Jika ada thread lain yang sedang menunggu (diblokir) di sem_wait() pada semaphore ini, sistem operasi akan membangunkan salah satunya.

Fungsi-Fungsi Semaphore

Semaphore bukan bagian dari standar Pthreads inti, jadi perlu menyertakan <semaphore.h>.

  • sem_t my_sem;: Mendeklarasikan variabel semaphore.

  • sem_init(&my_sem, 0, initial_value);: Menginisialisasi semaphore.

    • 0: Menandakan semaphore ini hanya dipakai oleh thread dalam proses yang sama.

    • initial_value: Nilai awal dari penghitung semaphore.

  • sem_wait(&my_sem);: Menunggu atau mengurangi nilai.

  • sem_post(&my_sem);: Memberi sinyal atau menaikkan nilai.

  • sem_destroy(&my_sem);: Membersihkan semaphore setelah selesai.

Rangkuman: Tabel Fungsi-Fungsi Penting Pthreads

FungsiKeteranganKapan DigunakanParameter Penting
Manajemen Thread
pthread_createMembuat dan memulai eksekusi sebuah thread baru.Ini adalah titik awal dari paralelisasi, di mana main thread “melahirkan” worker thread baru.&thread_handle: Pointer ke pthread_t untuk menyimpan ID thread baru.

NULL: Atribut thread (biasanya default/NULL).

nama_fungsi: Pointer ke fungsi yang akan dijalankan oleh thread (harus void* func(void*)).

&args: Pointer ke argumen yang akan diberikan ke nama_fungsi.
pthread_joinMemblokir thread pemanggil (misal, main) sampai thread yang dituju selesai.Wajib dipanggil oleh main thread untuk menunggu semua worker thread selesai, memastikan semua pekerjaan tuntas sebelum program berakhir.thread_handle: ID dari thread yang akan ditunggu.

NULL: Pointer untuk menyimpan nilai kembalian dari thread (opsional).
Sinkronisasi: Mutex
pthread_mutex_initMenginisialisasi variabel mutex sebelum digunakan.Harus dipanggil sekali untuk setiap mutex sebelum thread-thread dibuat.&my_mutex: Pointer ke variabel pthread_mutex_t.

NULL: Atribut mutex (biasanya default/NULL).
pthread_mutex_lockMengunci mutex. Jika mutex sudah dikunci oleh thread lain, thread ini akan diblokir (menunggu).Dipanggil sebelum memasuki Critical Section untuk melindungi data bersama dari race condition.&my_mutex: Pointer ke mutex yang ingin dikunci.
pthread_mutex_unlockMelepaskan kunci mutex, memungkinkan thread lain yang menunggu untuk mengambilnya.Dipanggil setelah keluar dari Critical Section. Lupa memanggil ini akan menyebabkan deadlock.&my_mutex: Pointer ke mutex yang ingin dilepaskan.
pthread_mutex_destroyMembersihkan sumber daya yang digunakan oleh mutex.Dipanggil setelah semua thread selesai dan mutex tidak lagi dibutuhkan.&my_mutex: Pointer ke mutex yang akan dihancurkan.
Sinkronisasi: Semaphore
sem_initMenginisialisasi sebuah semaphore dengan nilai awal.Untuk menyiapkan semaphore, misalnya dalam masalah Produsen-Konsumen, di mana kita perlu menghitung “slot kosong” dan “item terisi”.&my_sem: Pointer ke variabel sem_t.

0: Menandakan semaphore hanya untuk thread dalam proses ini.

initial_value: Nilai awal penghitung semaphore.
sem_waitMenunggu semaphore. Jika nilai semaphore > 0, nilainya dikurangi 1 dan lanjut. Jika 0, thread diblokir.Digunakan oleh thread yang perlu menunggu sebuah kondisi terpenuhi. Contoh: Konsumen memanggil sem_wait pada semaphore “item terisi”.&my_sem: Pointer ke semaphore yang akan ditunggu.
sem_postMemberi sinyal pada semaphore (menaikkan nilainya sebanyak 1). Jika ada thread yang menunggu, salah satunya akan dibangunkan.Digunakan oleh thread yang telah memenuhi sebuah kondisi. Contoh: Produsen memanggil sem_post pada semaphore “item terisi” setelah menaruh item.&my_sem: Pointer ke semaphore yang akan diberi sinyal.
sem_destroyMembersihkan sumber daya yang digunakan oleh semaphore.Dipanggil setelah semaphore tidak lagi dibutuhkan.&my_sem: Pointer ke semaphore yang akan dihancurkan.

Catatan Kompilasi: Jangan lupa untuk menambahkan flag -lpthread saat mengompilasi program yang menggunakan Pthreads. Contoh: gcc program.c -o program -lpthread.

Summary

Ketika Mutex tidak cukup untuk mengatur masalah sinkronisasi yang bergantung pada urutan, Semaphores hadir sebagai solusi yang lebih kuat. Semaphore adalah penghitung atomik yang menggunakan operasi sem_wait (untuk menunggu/mengurangi) dan sem_post (untuk memberi sinyal/menambah) untuk mengelola akses ke sumber daya secara terkontrol, sehingga ideal untuk menyelesaikan masalah klasik seperti Produsen-Konsumen di mana satu thread harus menunggu sinyal dari thread lain.