Anda di halaman 1dari 16

Sinkronisasi dengan Perangkat Keras dan

Semafor
Peran Hardware Dalam Proses Sinkronisasi
Sebelum adanya berbagai macam teknik sinkronisasi seperti yang ada sekarang,
para programmer sering memanfaatkan fasilitas yang telah diberikan oleh
hardware dari komputer. Sehingga sinkronisasi tidak akan terlepas dari peran
hardware.
Mengapa programmer tidak memakai pendekatan dari sisi software? hal ini
disebabkan karena sulit dan kompleksnya implementasi sinkronisasi yang akan
membawa kepada turunnya performa dari produk yang dibuat.

Metode dalam sinkronisasi hardware


Seperti yang telah kita ketahui bahwa, sinkronisasi haruslah mutual exclusive,
atau dengan kata lain, harus ada satu atau sekelompok instruksi yang tidak dapat
diberhentikan pada waktu eksekusi (sifat mutual exclusive). Jadi, solusi untuk
sinkronisasi dengan cara pendekatan hardware lebih menekankan kepada usahausaha untuk membuat suatu atau sekelompok instruksi menjadi mutual exclusive.
Pendekatan dari sisi Hardware dapat dibagi menjadi dua:
1. Processor Synchronous
2. Memory Synchronous

Processor Synchronous
Central Processing Unit, CPU, mempunyai suatu mekanisme yang dinamakan
interrupt. Di dalam sistim operasi, mekanisme ini digunakan secara intensif, atau
dengan kata lain, banyak konsep-konsep sistim operasi yang menggunakan
mekanisme ini. Sebagai contoh : system call, process scheduling, dsb.
Berbicara mengenai sinkronisasi berarti kita mengasumsikan bahwa akan ada 2
atau lebih proses yang sedang berjalan di komputer secara concurrent, atau dengan
kata lain konsep time-shared sudah diimplementasikan di sistim operasi.

Sistim time-shared yang sering diimplementasikan dengan algoritma RR (Round


Robin), memanfaatkan mekanisme interrupt di CPU. Jadi di dalam RR ada suatu
satuan waktu yg dinamakan quantum yang mana setiap quantum dibatasi oleh
satu software interrupt.
Teknisnya, akan ada suatu interrupt - yang biasanya adalah timer interrupt - yang
secara berkala akan menginterrupt sistim. Pada saat interrupt dilakukan sistim
operasi akan segera melakukan proses pergantian dari proses yang satu ke proses
yang lainnya sesuai dengan algoritma.
Seperti yang telah dikatakan di atas, isu yang ada di sini adalah, ada satu atau
sekelompok instruksi yang tidak dapat diberhentikan sampai satu atau sekelompok
instruksi tersebut selesai.
Adalah sangat jelas bahwa yang membuat suatu instruksi diberhentikan adalah
mekanisme yang di sistim operasi (baca mengenai process scheduling ).
Mekanisme ini sangat bergantung kepada mekanisme interrupt dari hardware. Jadi,
jika kita dapat menon-aktifkan interrupt pada saat critical section tersebut, maka
masalah sinkronisasi dapat terselesaikan.
Ternyata para designer komputer melihat celah ini, dan sekarang ini sudah hampir
semua komputer yang ada telah mengimplementasi instruksi mesin yang mana
instruksi ini akan menon-aktifkan serfis interrupt, dan ada instruksi yang lain yang
akan mengaktifkan interrupt tersebut.
Sebagai contoh sederhana, kita akan melihat contoh program dari prosesor Atmel
ARM tm (contoh ini diambil karena prosesor ini mudah didapatkan dan harganya
tidak terlalu mahal, serta ada dev-kitnya, silahkan merujuk
ke http://www.atmel.com ).
mainModul :
00 CLI
01 ADD r1,r2
02 ....
03 SBI
04 ..

'
'
'
'
'
'
'

masuk ke Critical Section dengan cara


men-disable interrupt
Critical Section
Critical Section
pergi dari Critical Section dengan cara
men-enable interrupt
Remainder Section

Pada baris ke 0, prosesor akan menon-aktifkan interrupt, instruksi - instruksi


selanjutnya tidak akan diganggu oleh interrupt. Selanjut setelah keluar dari critical
section, pada baris 3, prosesor akan mengaktifkan kembali interrupt sehingga
mekanisme scheduling di sistim operasi dapat berjalan kembali.
Bila kita melihat dari yang di atas, terlihat bahwa dengan mekanisme ini saja sudah
cukup mengatasi isu yang ada. Tetapi ternyata mekanisme ini tidak terlalu berhasil
di dalam lingkungan multiprocessor. Jikalau kita menon-aktifkan interrupt, maka

yang dinon-aktifkan hanya satu prosesor, hal ini dapat mengakibatkan hal - hal
yang tidak diinginkan.

Memory Synchronous
Dilihat dari nama mekanismenya, maka kita sudah dapat memprediksi bahwa
mekanisme ini akan menggunakan jasa memori. Memang hal tersebut benar,
mekanisme memory synchronous memakai suatu nilai yang disimpan di memori,
dan jikalau suatu proses berhasil mengubah nilai ini, maka proses ini akan
meneruskan ke instruksi selanjutnya, jika tidak, maka proses ini akan berusaha
terus untuk dapat mengubahnya.
Jika dilihat dari paragraf di atas, mekanisme ini lebih cocok dikategorikan sebagai
pendekatan dari software. Tetapi, jika kita perhatikan lebih lanjut, ternyata
mekanisme ini memerlukan jasa hardware. Syarat yang harus dipenuhi agar
mekanisme ini dapat berjalan adalah perlunya hardware mempunyai kemampuan
untuk membuat suatu instruksi dijalankan secara atomic. Pengertian dari
instruksi atomic adalah satu atau sekelompok instruksi yang tidak dapat
diberhentikan sampai instruksi tsb selesai. Detil mengenai hal ini akan dibicarakan
di bagian - bagian selanjutnya.
Sebagai contoh, kita dapat memperhatikan contoh program Java tm yang ada di
bawah ini :
00 boolean testAndSet( boolean variable[] )
01
{
02
boolean t = variable[0];
03
variable[0] = true;
04
return t;
05
}
.....
56 while (testAndSet(lock)) { /* do nothing
57 // Critical Section
58 Lock[0] = false;
59
// Remainder Section

*/ }

method testAndSet haruslah bersifat atomic , sehingga method ini dianggap


sebagai satu instruksi mesin. Perhatikan pada baris 56 dimana method ini dipakai.
Pada baris ini proses berusaha untuk mengubah nilai dari variable reference lock.
Jikalau ia tidak berhasil maka akan terus mencoba, tapi jika berhasil maka proses
akan masuk ke bagian kritis dan setelah ini proses akan mengubah nilai dari lock
sehingga memberikan kemungkinan proses lain untuk masuk.
Janganlah bingung dengan lock, boolean [], yang terkesan aneh. Hal ini bukanlah
bagian dari sinkronisasi tetapi hanyalah suatu bagian dari konsep pass-byreference dan pass-by-value dari Javatm, untuk lebih lanjut mengenai konsep ini

dapat dibaca buku - buku programming javatm. Satu catatan di sini adalah, contoh
ini hanyalah sebuah ilustrasi dan tidak dapat dicompile dan dijalankan, karena
Javatmkonsep atomic instruction di Javatm bersifat transparan dari sisi programmer
(akan dijelaskan pada bagian-bagian selanjutnya).
Keunggulan dari memory synchronous adalah pada lingkungan multiprocessor,
semua processor akan terkena dampak ini. Jadi semua proses yang berada di
processor, yang ingin mengakses critical section, meskipun berada di processor
yang berbeda - beda, akan berusaha untuk mengubah nilai yang dimaksud.
Sehingga semua processor akan tersinkronisasi.

Instruksi Atomic
Seperti yang telah dijelaskan pada bagian sebelumnya, instruksi atomic adalah satu
atau sekelompok instruksi yang tidak dapat diberhentikan sampai instruksi tersebut
selesai. Kita telah memakai instruksi ini pada method testAndSet.
Instruksi yang dimaksud di sini adalah instruksi-instruksi pada high-level
programming, bukanlah pada tingkat instruksi mesin yang memang sudah bersifat
atomic. Sebagai contoh : i++ pada suatu bahasa pemrograman akan
diinterpertasikan beberapa instruksi mesin yang bersifat atomic sbb :
00 Load R1,i ' load nilai i ke register 1
01 Inc R1
' tambahkan nilai register 1 dengan angka 1
02 Store i,R1 ' simpan nilai register 1 ke i

instruksi baris 00-02 bersifat atomic , tetapi i++ tidak bersifat atomic, mengapa?
sebagai contoh kasus, katakanlah sekarang processor baru menyelesaikan baris 01,
dan ternyata pada saat tersebut interrupt datang, dan menyebabkan processor
melayani interrupt terlebih dahulu. Hal ini menyebabkan terhentinya instruksi i++
sebelum instruksi ini selesai. Jikalau instruksi ini (i++) bersifat atomic, maka
ketiga instruksi mesin tsb tidak akan diganggu dengan interrupt.
Perlu diketahui bahwa instruksi ini bukanlah seperti pada processor
synchronous yang mana akan mematikan interrupt terlebih dahulu, tetapi instruksi
ini sudah build-in di processor.
Designer processor dapat mengimplementasi konsep ini dengan dua cara yaitu :
1. mengimplementasi instruksi yg build-in
2. mengimplementasi processor mampu membuat suatu instruksi
menjadi atomic

Intel Pentium ternyata memakai cara yang kedua, yaitu dengan adanya suatu
perintah LOCK-Assert. Dengan perintah ini maka semua instruksi dapat dijadikan
atomic. Sedangkan SPARC dan IBM mengimplementasikan suatu rutin yang
bersifat atomic seperti swap dan compareAndSwap.

Semafor
Sejarah Semafor
Telah dikatakan di atas bahwa pada awalnya orang-orang memakai konsep-konsep
sinkronisasi yang sederhana yang didukung oleh hardware, seperti pemakaian
interrupt atau pemakaian rutin-rutin yang mungkin telah diimplementasi oleh
hardware.
Pada tahun 1967, Djikstra mengajukan suatu konsep dimana kita memakai suatu
variable integer untuk menghitung banyaknya proses yang sedang aktif atau yang
sedang tidur. Tipe dari variable ini dinamakan semafor.
Tahun-tahun berikutnya, semafor banyak dipakai sebagai primitif dari mekanisme
sinkronisasi yang lebih tinggi dan kompleks lagi. Sebagai contoh : monitor dari
Javatm. Selain untuk hal tersebut, kebanyakkan semafor juga digunakan untuk
sinkronisasi dalam komunikasi antar device (perangkat keras).
Konsep dan Pengertian Semafor
Konsep semafor yang diajukan oleh Djikstra terdiri dari 2 subrutin yang bernama P
dan V. Nama P dan V berasal dari bahasa Belanda yang berarti Naik dan Turun
atau Wait dan Signal. Untuk pembahasan kali ini, kita akan memakai Wait dan
Signal.
Subrutin wait akan memeriksa apakah nilai dari semafor tersebut di atas 0. Jika ya,
maka nilainya akan dikurangi dan akan melanjutkan operasi berikutnya. Jika tidak
maka proses yang menjalankan wait akan menunggu sampai ada proses lain yang
menjalankan subrutin signal.
Satu hal yang perlu diingat adalah subrutin wait dan signal haruslah bersifat
atomic. Di sini kita lihat betapa besarnya dukungan hardware dalam proses
sinkronisasi.
Nilai awal dari semaphore tersebut menunjukkan berapa banyak proses yang boleh
memasuki critical section dari suatu program. Biasanya untuk mendukung
sifat mutual exclusive , nilai ini diberi 1.

Perlu ditekankan di sini, bahwa semafor bukan digunakan untuk menyelesaikan


masalah critical section saja, melainkan untuk menyelesaikan permasalahan
sinkronisasi secara umum.
Subrutin wait
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
semaphore tersebut dan menjalankan operasi yang lain.
Arti dari harga semafor dalam kasus ini adalah hanya boleh 1 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. spinlock waiting
2. non-spinlock waiting
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. Keuntunganspinlock 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 perintahperintah yang berguna.
Berbeda dengan spinlock waiting , non-spinlock waiting, memanfaatkan fasilitas
sistim 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
00 void waitSpinLock(int semaphore[] )
01 {
02
while(semaphore[0] <= 0)
{ .. Do nothing .. } // spinlock
03
semaphore[0]--;
04 }

10 void synchronized
waitNonSpinLock( int semaphore [])
11 {
12
while(semaphore[0] <= 0)
13
{
14
wait(); // blocks thread
15
}
16
semaphore[0]--;
17 }

Perbedaan dari kedua subrutin ini adalah terletak pada aksi dari kondisi nilai
semafor kurang atau sama dengan dari 0 (nol). Untuk yang spinlock , kita dapat
melihat proses akan berputar-putar di while baris no 2 (maka itu
disebut spinlock atau menunggu dengan berputar). Sedangkan pada non-spinlock,
proses dengan mudah memanggil perintah wait, setelah itu sistim 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 objek. Pembahasan mengenai hal ini sudah
diluar dari konteks buku ini, jadi untuk lebih lanjut silahkan merujuk kepada buku
Javatm pegangan anda.
Subrutin signal
Karena subrutin wait memiliki 2 versi maka hal ini juga berpengaruh kepada
subrutin signal. Subrutin signal akan terdiri dari 2 versi sesuai dengan yang ada di
subrutin wait.
Marilah kita lihat listing programnya
00
01
02
03
10
11
12
13
14
15
16

void signalSpinLock( int semaphore [])


{
semaphore[0]++;
}
void synchronized
signalNonSpinLock( int semaphore [])
{
semaphore[0]++;
notifyAll(); // membawa waiting thread
// ke ready queue
}

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

Perlu diketahui di sini bahwa setelah semaphore 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.

Macam - macam 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 sistim operasi yang hanya mengimplementasi binary semaphore sebagai
primitif, sedangkan counting semaphore dibuat dengan memakai primitif ini.
Untuk lebih detil mengenai cara pembuatancounting semaphore dapat dilihat pada
bagian berikutnya.
Perlu diketahui di sini bahwa, ada beberapa jenis dari counting semaphore. Salah
satu jenisnya adalah semafor yang tidak mencapai nilai negatif (seperti yang
dicontohkan pada bagian sebelumnya). Jenis yang lain adalah semaphore yang
dapat mencapai nilai negatif.

Masalah - Masalah Sinkronisasi yang Dapat Diselesaikan


oleh Semafor
Seperti yang telah dikatakan di atas bahwa semafor tidak hanya digunakan untuk
menyelesaikan masalah critical section saja, tetapi menyelesaikan masalah
sinkronisasi yang lainnya. Bahkan tidak jarang semafor dijadikan primitif untuk
membuat solusi dari masalah sinkronisasi yang kompleks.
Semafor menyelesaikan masalah critical section
Kita telah panjang lebar melihat bagaimana penggunaan semafor untuk
menyelesaikan masalah sinkronisasi dengan memakai contoh pada critical section .
Pada bagian ini, kita akan melihat lebih dekat lagi apa dan seberapa besar
sebenarnya peran dari semafor itu sendiri sebagai solusi dalam 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 mengenai sinkronisasi dapat
dipenuhi.
Seperti yang telah dijelaskan pada bagian sebelumnya, agar critical section dapat
terselesaikan ada 3 syarat yaitu :
1. Mutual exclusive
2. Make progress
3. Bounded waiting
Sekarang marilah melihat lagi listing program yg 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
semaphore dengan policy nilai diberikan 1, dapat menjamin syarat yang
pertama, 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 semaphore 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 yang
sedang berada di critical section memanggil signal.
Contoh suatu potongan program critical section yang memakai semaphore dapat
dilihat di bawah ini. Catatan bahwa program di bawah ini hanyalah pseudo code.
00 wait(semaphoreVar)
01 // critical section
02 signal(semaphoreVar)

Baris 00 dan 02 menjamin adanya mutual exclusive. Sedangkan mekanisme


semaphore menjamin kedua syarat yang lainnya.
Semafor menyelesaikan masalah sinkronisasi antar proses
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 tau bahwa proses lain telah menyelesaikan instruksi tertentu.
Semafor adalah jawaban yang cukup baik dan mudah. Marilah kita lihat potongan
program di bawah ini
Nilai semaphore diset menjadi 0
Proses 1
56 print "satu"
57 signal(semaphoreVar)

17
18

Proses 2
wait(semaphoreVar)
print "dua"

siapapun yang berjalan lebih cepat, maka keluarannya pasti "satu" baru "dua". Hal
ini disebabkan karena jika proses 2 jalan terlebih dahulu, maka dia akan menunggu
(nilai semafor adalah 0) sampai proses 1 memanggil signal. Sebaliknya jika proses
1 jalan terlebih dahulu, dia akan memanggil signal untuk memberikan jalan kepada
proses 2.
Solusi Pembuatan Counting Semaphore dari Binary Semaphore
Pembuatan counting semaphore banyak dilakukan para programmer 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;

subrutin waitC dapat dilihat di bawah ini :


02
03
04
05
06
07
08

wait (S1);
C--;
if ( C < 0 ) {
signal (S1);
wait (S2);
}
signal (S1);

subrutin signalC dapat dilihat di bawah ini :


09
10
11
12
13
14

wait (S1);
C++;
if (C <= 0)
signal (S2);
else
signal (S1);

Kita memerlukan 2 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.
Jika diperhatikan pada subrutin waitC dan signalC di awal dan akhir diberikan
pasangan wait dan signal dari binary semaphore. Fungsi dari binary
semaphore yang ini adalah untuk menjamin critical section(instruksi wait dan
signal dari semafor bersifat atomic, maka begitu pula untuk waitC dan signalC,
jadi kegunaan lain semafor adalah untuk membuat suatu subrutin menjadi
bersifat atomic).
Binary semaphore S2 sendiri digunakan sebagai tempat menunggu giliran prosesproses. Cara menunggu proses - proses tersebut bisa spinlock atau nonspinlock 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 bangunkan mereka semua untuk berkompetisi.
Mengapa pada baris 05 dilakukan signal untuk S1? Alasannya karena seperti yang
telah kita ketahui bahwa semaphore 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 didalamnya menunggu proses yang lain untuk
signal. Dengan kata lain deadlock terjadi. Jadi, baris 05 perlu dilakukan untuk
mengeliminir 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 dan akhirnya 08 di mana
dia memanggil signal S1 yang akan mewakili kebutuhan di baris 12.

Semafor dalam Producer Consumer Problem


Latar belakang dari permasalahan ini sudah dibahas di atas. Maka langsung saja
kita lihat bagaimana implementasi semafor dalam permasalahan ini.
Berhubung permasalahan dan solusi dari masalah ini sudah dibahas, maka program
Java tm yang ada di bawah ini tidak dilengkapi oleh penjelasan. Hal ini dilakukan
karena program ini hanya ditujukan agar pembaca memiliki gambaran umumnya
saja.
BinarySemaphore.java
public class BinarySemaphore
{
public BinarySemaphore()
{
semaphore = 1;
}
public BinarySemaphore(int i)
{
semaphore = i;
}
public synchronized void waitS()
{
try
{
while(semaphore == 0)
wait();
semaphore = 0;
}
catch (InterruptedException ie)
{
}
}
public synchronized void signalS()
{
semaphore = 1;
notifyAll();
}
private int semaphore;
}

CountingSemaphore.java
public class CountingSemaphore
{
public CountingSemaphore( int now )
{
semaphore = now;
mutex = new
BinarySemaphore();
S1 = new BinarySemaphore(0);
}

public void waitS()


{
mutex.waitS();
semaphore--;
if (semaphore <
0)
{
mutex.signalS();
S1.waitS();
}
mutex.signalS();
}
public void signalS()
{
mutex.waitS();
semaphore++;
if (semaphore <= 0)
{
S1.signalS();
}
else
mutex.signalS();
}
int
semaphore;
BinarySemaphore
BinarySemaphore

mutex;
S1;

Consumer.java
public class Consumer extends Thread
{
public Consumer (BinarySemaphore mutex,
CountingSemaphore full,CountingSemaphore empty,
SharedBuffer buff)
{
this.mutex = mutex;
this.full = full;
this.empty = empty;
this.buff = buff;
}
public void run()
{
try
{
while(true)
{
full.waitS();
System.out.print("There's a buffer:");
mutex.waitS();
System.out.println(buff.getBuffer());
mutex.signalS();
empty.signalS();
sleep(1000);

}
}catch (InterruptedException ie)

{}
}
private
private
private
private

BinarySemaphore mutex;
CountingSemaphore full;
CountingSemaphore empty;
SharedBuffer buff;

Producer.java
public class Producer extends Thread
{
public Producer(BinarySemaphore mutex,
CountingSemaphore full,CountingSemaphore
empty,SharedBuffer buff)
{
this.mutex = mutex;
this.full = full;
this.empty = empty;
this.buff = buff;
}
public void run()
{
try
{
while(true)
{
empty.waitS();
Integer random =
new Integer(
(int)(Math.random() * 10));
System.out.println(
"producer add : " + random);
mutex.waitS();
buff.addBuffer(random);
mutex.signalS();
full.signalS();
sleep(1);
}
}catch (InterruptedException ie)
{}
}
private
private
private
private
}

BinarySemaphore mutex;
CountingSemaphore full;
CountingSemaphore empty;
SharedBuffer buff;

SharedBuffer.java
class SharedBuffer
{
public SharedBuffer(int max)
{
buffer = new Object[max];
this.max = max;
i = 0;
j = 0;
}
public void addBuffer(Object buff)
{
buffer[i] = buff;
i = (i + 1) % max;
}
public Object getBuffer()
{
j = (j + 1) % max;
return buffer[j];
}
private Object buffer[];
private int max;
private int i;
private int j;
`}
public class ConsumerProducerTest
{
public static void main(String args[])
{
BinarySemaphore mutex = new BinarySemaphore();
CountingSemaphore full = new CountingSemaphore(0);
CountingSemaphore empty = new
CountingSemaphore(MAX);
SharedBuffer buff = new SharedBuffer(MAX);
Consumer consumer = new Consumer(
mutex,full,empty,buff);
Producer producer = new Producer(
mutex,full,empty,buff);
producer.start();
consumer.start();
}
public static final int MAX = 25;
}

Semaphore dalam masalah Readers/Writers


Solusi dari sisi semaphore dalam menyelesaikan hal ini ada beberapa macam.
Mengingat banyaknya kombinasi solusi maka pada kali ini akan dibahas solusi
yang tidak menghasilkan deadlock dan starvation.

Seperti halnya Dinning Philosopher problem, masalah ini juga akan dibahas lebih
detil pada bagian berikutnya.
Semafor dalam masalah Dining Philosophers
Karena latar belakang dan konsep dari permasalah ini sudah dijelaskan, maka pada
bagian ini hanya akan dijelaskan bagaimana menggunakan semaphore untuk
menyelesaikan masalah ini.
Untuk pembahasan lebih rinci dapat dilihat pada bagian selanjutnya.

Semafor di dalam Pemrograman


Pemrograman windows
Win32API (Windows 32 bit Application Programming Interface), menyediakan
fungsi-fungsi yang berkaitan dengan semafor. Fungsi-fungsi yang ada antara lain
adalah membuat semaphore dan menambahkan semafor.
Hal yg menarik dari semaphore yg ada di Windows tm adalah tersedianya dua jenis
semafor. Binary semaphore dan counting semaphore. Selain itu, windows juga
menyediakan seberapa besar angka yg dapat disimpan di semafor. Jadi selain kita
dapat menentukan nilai awal, semaphore di windows jg dapat menspesifikasi nilai
maksimal dari semafor tersebut.
Bila biasanya thread yang menunggu di semafor aturannya tidak ditentukan,
ternyata di Windows aturan untuk mengantrinya adalah FIFO atau sering
disebut First In First Out. Jadi Thread yang pertama kali wait, maka menjadi yang
pertama kali keluar dari wait.

Anda mungkin juga menyukai