• Tidak ada hasil yang ditemukan

inisialisasi awal: int mutex = 1; while (true) { wait (mutex); // critical section signal (mutex); // remainder section }

21.4. Wait dan Signal

Seperti yang telah dikatakan di atas, bahwa di dalam subrutin ini, proses akan memeriksa harga dari semafor, apabila harganya 0 atau kurang maka proses akan menunggu, sebaliknya jika lebih dari 0, maka proses akan mengurangi nilai dari semafor tersebut dan menjalankan operasi yang lain. Arti dari harga semafor dalam kasus ini adalah hanya boleh satu proses yang dapat melewati subrutin wait pada suatu waktu tertentu, sampai ada salah satu atau proses itu sendiri yang akan memanggil signal.

Bila kita perhatikan lebih kritis lagi, pernyataan "menunggu" sebenarnya masih abstrak. Bagaimanakah cara proses tersebut menunggu, adalah hal yang menarik. Cara proses menunggu dapat dibagi menjadi dua:

1. Tipe Spinlock. Dalam tipe Spinlock, proses melakukan Spinlock waiting, yaitu melakukan iterasi(looping) secara terus menerus tanpa menjalankan perintah apapun. Dengan kata lain, proses terus berada di running state. Tipe Spinlock, yang biasa disebut busy waiting, menghabiskan CPU cycle. Pseudocode bisa dilihat di atas. Spinlock waiting berarti proses tersebut menunggu dengan cara menjalankan perintah-perintah yang tidak ada artinya. Dengan kata lain proses masih running state di dalam spinlock waiting. Keuntungan spinlock pada lingkungan multiprocessor adalah, tidak diperlukan context switch. Tetapi spinlock yang biasanya disebut busy waiting ini menghabiskan cpu cycle karena, daripada proses tersebut melakukan perintah-perintah yang tidak ada gunanya, sebaiknya dialihkan ke proses lain yang mungkin lebih membutuhkan untuk mengeksekusi perintah-perintah yang berguna.

2. Tipe Non-Spinlock. Dalam tipe Non-Spinlock, proses akan melakukan Non-Spinlock waiting, yaitu memblock dirinya sendiri dan secara otomatis masuk ke dalam waiting queue. Di dalam

waiting queue, proses tidak aktif dan menunggu sampai ada proses lain yang membangunkannya dan membawanya ke ready queue. Untuk lebih mudahnya, silahkan lihat pseudocode method wait dan method signal yang bertipe Non-Spinlock dalam bahasa pemrograman java. Berbeda dengan spinlock waiting, non-spinlock waiting, memanfaatkan fasilitas sistem operasi. Proses yang melakukan non-spinlock waiting akan memblock dirinya sendiri dan secara otomatis akan membawa proses tersebut ke dalam waiting queue. Di dalam waiting queue ini proses tidak aktif dan menunggu sampai ada proses lain yang membangunkan dia sehingga membawanya ke ready

queue.

Maka marilah kita lihat listing subrutin dari kedua versi wait. Perbedaan dari kedua subrutin ini adalah terletak pada aksi dari kondisi nilai semafor kurang atau sama dengan dari 0 (nol). Untuk

spinlock, disini kita dapat melihat bahwa proses akan berputar-putar di while baris 02 (maka itu

disebut spinlock atau menunggu dengan berputar). Sedangkan pada non-spinlock, proses dengan mudah memanggil perintah wait, setelah itu sistem operasi akan mengurus mekanisme selanjutnya. Jangan bingung dengan kata synchronized pada baris 10. Kata ini ada karena memang konsep dari Javatm, apabila sebuah proses ingin menunggu, maka proses tersebut harus menunggu di suatu obyek. Pembahasan mengenai hal ini sudah diluar dari konteks buku ini, jadi untuk lebih lanjut silahkan merujuk kepada buku Javatmpegangan anda.

Contoh 21.8. waitSpinLock

00 void waitSpinLock(int semaphore[]) 01 {

02 while(semaphore[0] <= 0)

03 { .. Do nothing .. } // spinlock

03 semaphore[0]--;

04 }

05 void synchronized waitNonSpinLock( int semaphore []) 06 {

07 while(semaphore[0] <= 0)

08 {

09 wait(); // blocks thread

10 }

11 semaphore[0]--;

12 }

Karena subrutin wait memiliki dua versi maka hal ini juga berpengaruh terhadap subrutin signal. Subrutin signal akan terdiri dari dua versi sesuai dengan yang ada pada subrutin wait.

Contoh 21.9. signalSpinLock

00 void signalSpinLock( int semaphore [])

01 {

02 semaphore[0]++;

03 } 04

05 void synchronizedsignalNonSpinLock( int semaphore []) 06 {

07 semaphore[0]++;

08 notifyAll(); // membawa waiting thread

09 // ke ready queue

10 }

Letak perbedaan dari kedua subrutin di atas adalah pada notifyAll. NotifyAll berarti membangunkan semua proses yang sedang berada di waiting queue dan menunggu semafor yang disignal.

Perlu diketahui di sini bahwa setelah semafor disignal, proses-proses yang sedang menunggu, apakah itu spinlock waiting ataukah non-spinlock waiting, akan berkompetisi mendapatkan akses semafor tersebut. Jadi memanggil signal bukan berarti membangunkan salah satu proses tetapi memberikan kesempatan proses-proses untuk berkompetisi.

21.5. Jenis Semafor

Ada 2 macam semafor yang cukup umum, yaitu: 1. Binary semaphore

2. Counting semaphore

Binary semaphore adalah semafor yang bernilai hanya 1 dan 0. Sedangkan Counting semaphore

adalah semafor yang dapat bernilai 1 dan 0 dan nilai integer yang lainnya.

Banyak sistem operasi yang hanya mengimplementasi binary semaphore sebagai primitif, sedangkan counting semaphore dibuat dengan memakai primitif ini. Untuk lebih rinci mengenai cara pembuatan counting semaphore dapat dilihat pada bagian berikutnya.

Ada beberapa jenis counting semaphore, yaitu semafor yang dapat mencapai nilai negatif dan semafor yang tidak dapat mencapai nilai negatif (seperti yang telah dicontohkan pada bagian sebelumnya).

21.6. Critical Section Dan Semafor

Kita telah lihat bagaimana penggunaan semafor untuk menyelesaikan masalah sinkronisasi dengan memakai contoh pada masalah critical section. Pada bagian ini, kita akan melihat lebih dekat lagi apa dan seberapa besar sebenarnya peran dari semafor itu sendiri sebagai solusi dalam memecahkan masalah critical section.

Lihatlah pada kode-kode di bagian demo. Telitilah, bagian manakah yang harus dieksekusi secara

mutual exclusive, dan bagian manakah yang tidak. Jika diperhatikan lebih lanjut anda akan

menyadari bahwa akan selalu ada satu pasang instruksi wait dan signal dari suatu semafor.

Perintah wait digunakan sebagai pintu masuk critical section dan perintah signal sebagai pintu keluarnya. Mengapa semafor dapat dijadikan seperti ini? Hal ini disebabkan dengan semafor ketiga syarat utama sinkronisasi dapat dipenuhi.

Seperti yang telah dijelaskan pada bagian sebelumnya, agar critical section dapat terselesaikan ada tiga syarat yaitu:

1. Mutual exclusive 2. Make progress 3. Bounded waiting

Sekarang marilah melihat lagi listing program yang ada di bagian sebelumnya mengenai wait dan signal. Jika nilai awal dari semafor diberikan 1, maka artinya adalah hanya ada satu proses yang akan dapat melewati pasangan wait-signal. Proses-proses yang lainnya akan menunggu. Dengan kata lain, mekanisme semafor dengan policy nilai diberikan 1, dapat menjamin syarat yang pertama, yaitu mutual exclusive.

Bagaimana dengan syarat yang kedua, make progress? Sebenarnya pada waktu proses yang sedang berada di dalam critical section keluar dari bagian tersebut dengan memanggil signal, proses tersebut tidak memberikan akses ke critical section kepada proses tertentu yang sedang menunggu tetapi, membuka kesempatan bagi proses lain untuk berkompetisi untuk mendapatkannya. Lalu bagaimana jika ada 2 proses yang sedang menunggu dan saling mengalah? mekanisme semafor memungkinkan salah satu pasti ada yang masuk, yaitu yang pertama kali yang berhasil mengurangi nilai semafor menjadi 0. Jadi di sini semafor juga berperan dalam memenuhi syarat kedua.

Untuk syarat yang ketiga, jelas tampak bahwa semafor didefinisikan sebagai pasangan wait-signal.

Dengan kata lain, setelah wait, pasti ada signal. Jadi proses yang sedang menunggu pasti akan mendapat giliran, yaitu pada saat proses sedang berada di critical section memanggil signal.

21.7. Solusi Masalah Sinkronisasi Antar

Proses Dengan Semafor

Kadangkala kita ingin membuat suatu proses untuk menunggu proses yang lain untuk menjalankan suatu perintah. Isu yang ada di sini adalah bagaimana caranya suatu proses mengetahui bahwa proses yang lain telah menyelesaikan instruksi tertentu. Oleh karena itu digunakanlah semafor karena semafor adalah solusi yang cukup baik dan mudah untuk mengatasi hal tersebut.

Nilai semafor diset menjadi 0

Proses 1 Proses 2

56 print "satu" 17 wait(semaphoreVar)

57 signal(semaphoreVar) 18 print "dua"

siapa pun yang berjalan lebih cepat, maka keluarannya pasti "satu" kemudian diikuti oleh "dua". Hal ini disebabkan karena jika proses 2 berjalan terlebih dahulu, maka proses tersebut akan menunggu (nilai semafor = 0) sampai proses 1 memanggil signal. Sebaliknya jika proses 1 berjalan terlebih dahulu, maka proses tersebut akan memanggil signal untuk memberikan jalan terlebih dahulu kepada proses 2.

21.8. Modifikasi Binary Semaphore

Pembuatan counting semaphore banyak dilakukan para programer untuk memenuhi alat sinkronisasi yang sesuai dengannya. Seperti yang telah dibahas di atas, bahwa counting semaphore ada beberapa macam. Pada bagian ini, akan dibahas counting semaphore yang memperbolehkan harga negatif. Listing program di bawah ini diambil dari buku Silberschatz.

00 binary-semaphore S1,S2; 01 int C; 02 wait (S1); 03 C--; 04 if ( C < 0 ) { 05 signal (S1); 06 wait (S2); 07 } 08 signal (S1); 09 wait (S1); 10 C++; 11 if (C <= 0) 12 signal (S2); 13 else 14 signal (S1);

Kita memerlukan dua binary semaphore pada kasus ini, maka pada baris 00 didefinisikan dua

binary semaphore. Baris 01 mendefinisikan nilai dari semafor tersebut. Perlu diketahui di sini

bahwa waitC adalah wait untuk counting semaphore, sedangkan wait adalah untuk binary

semaphore.

Solusi Masalah Sinkronisasi Antar Proses Dengan Semafor

Jika diperhatikan pada subrutin waitC dan signalC di awal dan akhir diberikan pasangan wait dan signal dari binary semaphore. Fungsi dari binary semaphore ini adalah untuk menjamin critical

section (instruksi wait dan signal dari semafor bersifat atomik, maka begitu pula untuk waitC dan

signalC, jadi kegunaan lain semafor adalah untuk membuat suatu subrutin bersifat atomik).

Binary semaphore S2 sendiri digunakan sebagai tempat menunggu giliran proses-proses.

Proses-proses tersebut menunggu dengan cara spinlock atau non-spinlock tergantung dari implementasi binary semaphore yang ada.

Perhatikan baris 03 dan 04. Baris ini berbeda dengan apa yang sudah dijabarkan pada bagian sebelumnya. Karena baris ini maka memungkinkan nilai semafor untuk menjadi negatif. Lalu apa artinya bagi kita? Ternyata nilai negatif mengandung informasi tambahan yang cukup berarti bagi kita yaitu bila nilai semafor negatif, maka absolut dari nilai tersebut menunjukkan banyaknya proses yang sedang menunggu atau wait. Jadi arti baris 11 menyatakan bahwa bila ada proses yang menunggu maka semua proses dibangunkan untuk berkompetisi.

Mengapa pada baris 05 dilakukan signal untuk S1? Alasannya karena seperti yang telah kita ketahui bahwa semafor menjamin ketiga sifat dari critical section. Tetapi adalah tidak relevan bila pada saat waktu menunggu, waitC masih mempertahankan mutual exclusivenya. Bila hal ini terjadi, proses lain tidak akan dapat masuk, sedangkan proses yang berada di dalam menunggu proses yang lain untuk signal. Dengan kata lain deadlock terjadi. Jadi, baris 05 perlu dilakukan untuk menghilangkan sifat mutual exclusive pada saat suatu proses menunggu.

Pada baris 12 hanya menyatakan signal untuk S2 saja. Hal ini bukanlah merupakan suatu masalah, karena jika signal S2 dipanggil, maka pasti ada proses yang menunggu akan masuk dan meneruskan ke instruksi 07 kemudian ke instruksi 08 di mana proses ini akan memanggil signal S1 yang akan mewakili kebutuhan di baris 12.

21.9. Pemrograman Windows

Win32API (Windows 32 bit Application Programming Interface), menyediakan fungsi-fungsi yang berkaitan dengan semafor. Fungsi-fungsi yang ada antara lain adalah membuat semafor dan menambahkan semafor.

Hal yang menarik dari semafor yang terdapat di Windowstmadalah tersedianya dua jenis semafor yaitu, Binary semaphore dan counting semaphore. Pada Windowstm selain kita dapat menentukan nilai awal dari semafor, kita juga dapat menentukan nilai maksimal dari semafor. Setiap thread yang menunggu di semafor pada Windowstmmenggunakan metode antrian FIFO (First In First Out.)

21.10. Rangkuman

Hardware merupakan faktor pendukung yang sangat berperan dalam proses sinkronisasi. Banyak dari para perancang prosesor yang membuat fasilitas atomic instruction dalam produknya. Ada 2 metode dalam sinkronisasi hardware, yaitu: Processor Synchronous dan Memory Synchronous. Semafor merupakan konsep yang dibuat oleh Djikstra dengan mengandalkan sebuah variable integer dan fasilitas atomic instruction dari prosesor. Semafor merupakan primitif dalam pembuatan alat sinkronisasi yang lebih tinggi lagi. Semafor dapat menyelesaikan permasalahan seperti: Critical

section, sinkronisasi baris, counting semaphore, Dining philosopher, readers-writers, dan producer-consumer. banyak dipakai oleh para programer, sebagai contoh dapat dilihat di

pemrograman Win32API. Tetapi ternyata Javatmtidak menggunakan semafor secara explisit namun memakai konsep monitor yang dibangun dari semafor ini.

Banyak mesin yang menyediakan instruksi hardware istimewa yang tidak bisa di-Interrupt. Instruksi-instruksi semacam ini dikenal dengan nama Instruksi Atomik.

Sebuah semafor S adalah sebuah variabel integer yang, selain saat inisiasi, hanya bisa diakses oleh dua buah operasi atomik standar, wait dan signal.

Rujukan

[KennethRosen1999] Kenneth H Rosen. 1999. Discrete Mathematics and Its Application. McGraw Hill.

[Silberschatz2002] Abraham Silberschatz, Peter Galvin, dan Greg Gagne. 2002. Applied Operating

Systems. Sixth Edition. John Wiley & Sons.

[Silberschatz2005] Avi Silberschatz, Peter Galvin, dan Grag Gagne. 2005. Operating Systems

Concepts. Seventh Edition. John Wiley & Sons.

[Stallings2001] William Stallings. 2001. Operating Systems: Internal and Design Principles. Fourth Edition. Edisi Keempat. Prentice-Hall International. New Jersey.

[Tanenbaum1997] Andrew S Tanenbaum dan Albert S Woodhull. 1997. Operating Systems Design

and Implementation. Second Edition. Prentice-Hall.

Bab 22. Perangkat Sinkronisasi II

22.1. Pendahuluan

Sejauh ini, kita telah mengenal semafor sebagai perangkat keras sinkronisasi yang ampuh, lalu mengapa kita membutuhkan bahasa pemrograman untuk melakukan sinkronisasi? Alasan yang sederhana adalah karena ternyata implementasi semafor memiliki beberapa kelemahan. Kelemahan yang pertama adalah kenyataan bahwa semafor memerlukan implementasi di tingkat rendah, sesuatu hal yang kompleks untuk dilakukan kebanyakan orang. Bahasa pemrograman lebih mudah untuk dipelajari dan diimplementasikan. Kode semafor terdistribusi dalam seluruh program sehingga menyulitkan pemeliharaan. Hal ini merupakan kelemahan lain dari semafor. Sehingga jelas tampaknya, bahwa kita memerlukan konstruksi tingkat tinggi yang dapat mengatasi atau paling tidak mengurangi kelemahan-kelemahan yang terdapat dalam semafor.

22.2. Transaksi Atomik

Yang dimaksud dengan transaksi atomik adalah suatu transaksi yang dilakukan secara keseluruhan atau tidak dilakukan sama sekali. Sebagai ilustrasi adalah ketika dilakukan transfer dari rekening A ke rekening B terjadi kegagalan listrik, maka lebih baik tidak dilakukan perubahan terhadap balance setiap rekening. Disinilah digunakan instruksi atomik.

Keatomikan (atomicity) merupakan komponen penting dalam menghindari bahaya race condition. Operasi atomik dijamin hanya ada dua kemungkinan keluaran (contohnya berhasil atau gagal) dan ketika banyak proses berusaha melakukan operasi atomik dapat dipastikan hanya satu yang akan berhasil (meskipun semuanya dapat gagal).

Secara tipikal, keatomikan diimplementasikan dengan menyediakan mekanisme yang mencatat transaksi mana yang telah dimulai dan selesai atau dengan membuat salinan data sebelum dilakukan perubahan. Sebagai contoh banyak database mendukung mekanisme commit-rollback dalam penerapan transaksi atomik, dimana bila transaksi berhasil maka dilakukan commit tetapi bila transaksi gagal akan dilakukan rollback ke kondisi awal. Metode ini biasanya menyimpan perubahan dalam sebuah log. Bila sebuah perubahan berhasil dilakukan maka akan disimpan dalam log. Bila terjadi kegagalan maka hal tersebut tidak disimpan dalam log. Bila diperlukan kondisi akan diubah ke kondisi terakhir dari transaksi yang berhasil.

Pada tingkat hardware diperlukan instruksi seperti TestAndSet dan operasi increment/decrement. Bila diperlukan maka dapat dilakukan pencegahan pelayanan interupsi yang terjadi ketika transaksi dijalankan dimana transaksi tersebut harus selesai dijalankan barulah interupsi dilayani.

Keatomikan (atomicity) merupakan komponen penting dalam menghindari bahaya race condition. Operasi atomik dijamin hanya ada dua kemungkinan keluaran (contohnya berhasil atau gagal) dan ketika banyak proses berusaha melakukan operasi atomik dapat dipastikan hanya satu yang akan berhasil (meskipun semuanya dapat gagal).

Secara tipikal, keatomikan diimplementasikan dengan menyediakan mekanisme yang mencatat transaksi mana yang telah dimulai dan selesai atau dengan membuat salinan data sebelum dilakukan perubahan. Sebagai contoh banyak database mendukung mekanisme commit-rollback dalam penerapan transaksi atomik, dimana bila transaksi berhasil maka dilakukan commit tetapi bila transaksi gagal akan dilakukan rollback ke kondisi awal. Metoda ini biasanya menyimpan perubahan dalam sebuah log. Bila sebuah perubahan berhasil dilakukan maka akan disimpan dalam log. Bila terjadi kegagalan maka hal tersebut tidak disimpan dalam log. Bila diperlukan kondisi akan diubah ke kondisi terakhir dari transaksi yang berhasil.

Pada tingkat hardware diperlukan instruksi seperti TestAndSet dan operasi increment/decrement. Bila diperlukan maka dapat dilakukan pencegahan pelayanan interupsi yang terjadi ketika transaksi dijalankan dimana transaksi tersebut harus selesai dijalankan barulah interupsi dilayani.

22.3. Critical Region

Critical region adalah bagian dari program dan diamanatkan untuk selalu berada dalam keadaan

mutual exclusion. Perbedaan critical region ini dengan mutual exclusion biasa yang dibahas sebelumnya adalah critical region diimplementasikan oleh kompilator. Keuntungan menggunakan ini adalah programer tidak perlu lagi mengimplementasikan algoritma yang rumit untuk mendapatkan mutual exclusion.

Critical region memiliki sebuah komponen boolean yang menguji apakah bagian dari program

boleh masuk kedalam state critical region atau tidak. Jika nilai boolean ini true maka proses boleh masuk ke critical region. Jika boolean ini bernilai false bagian yang ini akan dimasukan kedalam sebuah antrian sampai nilai boolean ini bernilai true.

Dalam critical region dikenal ada 2 antrian: main queue dan event queue. Main queue berfungsi untuk menampung proses yang akan memasuki critical region hanya saja critical region masih digunakan oleh proses lain. Event queue berguna untuk menampung proses yang tidak dapat memasuki critical region karena nilai boolaen-nya bernilai false.

22.4. Monitor

Konsep monitor diperkenalkan pertama kali oleh Hoare (1974) dan Brinch Hansen (1975) untuk mengatasi beberapa masalah yang timbul ketika memakai semafor.

Dokumen terkait