Pembahasan soal ujian mid Sistem Operasi No 4
(Dosen Pengampu: Dr. Tech. Khabib Mustofa, S.Si, M.Kom)
Pseudocode dari soal no 4 aku kodekan dalam bahasa Java (dengan beberapa penyesuaian).
Ternyata memang ada masalah alias pseudocode (soal no 4) Producer dan Consumer TIDAK AMAN jika dijalankan secara kongkuren. Untuk lebih jelasnya, silakan teman-teman mengEKSPLORE SENDIRI, source code dan output (CONTOH KASUS) aku sertakan.
Mohon masukan dari teman-teman, barangkali ada kesalahan di programnya.
Source Code:
public class Buffer { private Vector buffer; private int bufferSize; private int count; public Buffer(int bufferSize) { this.buffer = new Vector(bufferSize); this.bufferSize = bufferSize; this.count = 0; } public synchronized void enterItem(String item) { buffer.add(item); System.out.println(item + " added."); if (buffer.size()>bufferSize) { System.err.println("\tBuffer overflow!!..."); } } public synchronized String removeItem() { Object result; try { result = buffer.remove(0); } catch (Exception e) { System.err.println("\tBuffer underflow!!..."); return ""; } System.out.println("" + result + " removed."); return "" + result; } public void incCount() { count++; } public void decCount() { count--; } public int getBufferSize() { return bufferSize; } public int getCount() { return count; } public synchronized String toString() { StringBuffer sb = new StringBuffer(buffer.size()); for (Object o:buffer) { if (o!=null) { sb.append("# "); } } return "" + count + ": " + sb.toString(); } } public class Producer extends Thread { private Buffer buffer; private long tts; private Consumer consumer; //-- String item; private int msgId = 0; public Producer(Buffer buffer, long tts) { this.buffer = buffer; this.tts = tts; setDaemon(false); } public void setConsumer(Consumer consumer) { this.consumer = consumer; } public void run() { while (true) { item = "msg " + ++msgId; if (buffer.getCount() == buffer.getBufferSize()) { try { Thread.sleep(tts); } catch (InterruptedException e) { //e.printStackTrace(); } } buffer.enterItem(item); buffer.incCount(); if (buffer.getCount() == 1) synchronized (consumer) { consumer.notifyAll(); } } } } public class Consumer extends Thread { private Buffer buffer; private long tts; private Producer producer; //-- private String item; public Consumer(Buffer buffer, long tts) { this.buffer = buffer; this.tts = tts; setDaemon(false); } public void setProducer(Producer producer) { this.producer = producer; } public void run() { while (true) { if (buffer.getCount() == 0) { try { Thread.sleep(tts); } catch (InterruptedException e) { //e.printStackTrace(); } } item = buffer.removeItem(); buffer.decCount(); if (buffer.getCount() == buffer.getBufferSize() - 1) { synchronized (producer) { producer.notifyAll(); } } System.out.println("Consumer consumes " + item); } } }
Output:
Untuk kasus buffer size=1:
msg 1 added.
msg 1 removed.
Consumer consumes msg 1
msg 2 added.
msg 2 removed.
Consumer consumes msg 2
msg 3 added.
msg 3 removed.
Consumer consumes msg 3
msg 4 added.
msg 4 removed.
Consumer consumes msg 4
msg 5 added.
msg 5 removed.
Consumer consumes msg 5
msg 6 added.
msg 6 removed.
Consumer consumes msg 6
msg 7 added.
msg 7 removed.
Consumer consumes msg 7
msg 8 added.
msg 8 removed.
Consumer consumes msg 8
msg 9 added.
msg 9 removed.
Consumer consumes msg 9
msg 10 added.
msg 10 removed.
Consumer consumes msg 10
msg 11 added.
msg 11 removed.
Consumer consumes msg 11
msg 12 added.
msg 12 removed.
Consumer consumes msg 12
msg 13 added.
Buffer overflow!!…
4 responses so far ↓
aji febri // November 23, 2008 at 5:49 pm |
Harusnya sebelum melakukan remove item, Consumer harus memastikan item telah tersedia. Kalau tidak salah, kode if (buffer.getCount() == 0) { Thread.sleep(tts) ….} tidak melakukan ini. Ia hanya mengecek sekali, kemudian sleep beberapa lama, setelah itu wake dan melakukan remove, meskipun bisa saja item pada buffer belum tersedia alias buffer-nya masih kosong. Kan tidak menjamin, setelah sleep beberapa lama, processor memberi kesempatan Producer mengisi buffer. Bisa saja prosessor masih memberikan waktu pada Consumer.
Bagaimana kalau pengecekannya diganti dengan while( buffer.getCount()==0) { }. Jadi selama masih kosong, do nothing. Cara itu untuk mencegah buffer underflow.
Untuk mencegah buffer overflow, bisa diganti pengecekan pada Producer menjadi while (buffer.getCount() == buffer.getBufferSize()) { }
Selama masih penuh, do nothing.
Aku sudah tes, dan outputnya tidak buffer overflow atau underflow.
Itu sih pendapatku. Coba saja.
curiousjava // December 8, 2008 at 12:43 am |
Makasi komentarnya mas Aji.
Kode ini aku buat berdasarkan algoritma yang memang dirancang untuk salah, jadi hasilnya memang harus salah kan
Solusinya (kalo disuru benerin algoritmanya) ya mengganti if dengan while, seperti yang mas Aji sebutkan.
Producer Consumer Problem « OOPCLASS2008 // December 4, 2008 at 10:28 am |
[...] hari lalu saya melihat postingan mengenai masalah Producer Consumer di sini. Teman saya yang mem-post-kan. Ternyata merupakan implementasi dari pseudocode soal di ujian sistem [...]
curiousjava // December 8, 2008 at 12:40 am |
emang dari soal ujian SO koq. Soalnya dibahas pas belajar kelompok bareng, tapi pembahasan waktu itu masih rancu, jadi ta’bikin aja programnya