Model proses yang didiskusikan sejauh ini telah     menunjukkan bahwa suatu proses adalah sebuah program yang     menjalankan eksekusi      
      tunggal. Sebagai contoh, jika sebuah proses menjalankan sebuah     program Word Processor, ada sebuah      
      tunggal dari instruksi-instruksi yang sedang     dilaksanakan.
      tunggal ini hanya memungkinkan proses untuk menjalankan satu     tugas pada satu waktu. Banyak sistem operasi modern telah     memiliki konsep yang dikembangkan agar memungkinkan sebuah     proses untuk memiliki eksekusi      
      , agar dapat secara terus menerus mengetik dan menjalankan     pengecek ejaan didalam proses yang sama, maka sistem operasi     tersebut memungkinkan proses untuk menjalankan lebih dari satu     tugas pada satu waktu. Pada subbab      
Multiprogramming    bertujuan untuk memaksimalkan penggunaan CPU dengan cara mengatur   alokasi waktu yang digunakan oleh CPU,sehingga proses berjalan   sepanjang waktu dan meperkecil waktu    
idle    . Untuk sistem yang bersifat    
uniprosesor    , hanya ada satu proses yang bisa berjalan setiap waktunya. Jika   proses yang ada lebih dari satu, maka proses yang lain harus   menunggu sampai CPU bebas dan siap untuk dijadwalkan   kembali.
Ketika sebuah proses memasuki sistem, proses itu     diletakkan di dalam      
      job queue           . Pada antrian ini terdapat seluruh proses yang berada dalam     sistem. Sedangkan proses yang berada pada memori utama, siap     dan menunggu untuk mengeksekusi disimpan dalam sebuah daftar     yang bernama      
      ready queue           . Antrian ini biasanya disimpan sebagai      
linked list      .      
Header      dari      
ready queue      berisi      
pointer      untuk PCB pertama dan PCB terakhir pada list. Setiap PCB     memiliki      
pointer field      yang menunjuk kepada PCB untuk proses selanjutnya dalam      
ready queue      .
Sistem operasi juga memiliki antrian lain. Ketika sebuah     proses dialokasikan ke CPU, proses tersebut berjalan sebentar     lalu berhenti, di-interupsi, atau menunggu suatu hal tertentu,   seperti selesainya suatu permintaan I/O. Dalam permintaan I/O,     bisa saja yang diminta itu adalah      
tape drive      , atau peralatan yang di-      
share      secara bersama-sama, seperti disk. Karena ada banyak proses     dalam sistem, disk bisa saja sibuk dengan permintaan I/O dari     proses lainnya. Untuk itu proses tersebut mungkin harus     menunggu disk tersebut. Daftar dari proses-proses yang menunggu     peralatan I/O tertentu disebut dengan      
      device queue           . Tiap peralatan memiliki      
device queue      -nya masing-masing.      
Gambar 3-4      .
Penjadwalan proses dapat direpresentasikan secara umum     dalam bentuk diagram antrian, seperti yang ditunjukkan oleh     
Gambar 3-5. Setiap kotak segi empat menunjukkan sebuah antrian.     Dua tipe antrian menunjukan antrian yang siap dan seperangkat      
device queues      . Lingkaran menunjukkan sumber daya yang melayani antrian, dan tanda panah      mengindikasikan alur dari proses-proses yang ada dalam sistem.
Sebuah proses baru pertama-tama diletakkan dalam      
ready queue      . Proses tersebut menunggu di dalam      
ready      antrian sampai dia dipilih untuk eksekusi, atau dengan kata lain     di-      
dispatched      . Begitu proses tersebut dialokasikan ke CPU dan sedang     berjalan, beberapa kemungkinan di bawah ini dapat terjadi:      
- Proses tersebut mengeluarkan permintaan I/O, lalu         ditempatkan dalam sebuah antrian I/O
 
- Proses tersebut dapat membuat sub proses yang baru         dan menunggu untuk di-terminasi          
 
- Proses tersebut dapat dikeluarkan secara paksa dari         CPU, sebagai hasil dari suatu interupsi, dan diletakkan          kembali dalam          ready queue         
 
Pada dua kemungkinan pertama (proses meminta I/O atau     membuat sub proses baru), proses berganti keadaan dari      
waiting state      menjadi      
ready state      , lalu diletakkan kembali dalam      
ready queue      . Proses akan meneruskan siklus ini sampai dia di-terminasi     , yaitu saat dimana proses tersebut dikeluarkan dari seluruh antrian     yang ada dan memiliki PCB-nya sendiri dan seluruh sumber daya          yang dia gunakan dialokasikan kembali.
Sebuah proses berpindah-pindah di antara berbagai     penjadwalan antrian seumur hidupnya. Sistem operasi harus     memilih dan memproses antrian-antrian ini berdasarkan     kategorinya dengan cara tertentu. Oleh karena itu, proses     seleksi ini harus dilakukan oleh      
      scheduler           yang tepat.
Dalam sistem      
batch      , seringkali proses yang diserahkan     lebih banyak daripada yang dapat dilaksanakan dengan segera.     Proses-proses ini disimpan pada suatu      
mass-storage device      (semacam disk), dimana proses tersebut disimpan untuk eksekusi     di lain waktu.      
      Long-term scheduler           , atau      
      job scheduler           , memilih proses dari tempat ini dan mengisinya ke dalam     memori. Sedangkan      
      short-term scheduler           , atau      
      CPU scheduler           , hanya memilih proses yang sudah siap untuk melakukan     eksekusi, dan mengalokasikan CPU untuk proses tersebut.
Hal yang cukup jelas untuk membedakan kedua jenis      
scheduler      ini adalah frekuensi dari eksekusinya.      
Short-term scheduler      harus memilih proses baru untuk CPU sesering mungkin. Sebuah     proses dapat mengeksekusi hanya dalam beberapa milidetik     sebelum menunggu permintaan I/O. Seringkali,      
short-term scheduler      mengeksekusi paling sedikit sekali setiap 100 milidetik. Karena     durasi waktu yang pendek antara eksekusi-eksekusi tersebut,      
short-term scheduler      seharusnya cepat. Jika memerlukan waktu 10 mili detik untuk     menentukan suatu proses eksekusi selama 100 mili detik, maka     10/(100 + 10) = 9 persen dari CPU sedang digunakan (atau     terbuang) hanya untuk pekerjaan penjadwalan.
Long-term scheduler      , pada sisi lain, mengeksekusi jauh lebih jarang. Mungkin ada     beberapa menit waktu yang dibutuhkan untuk pembuatan proses     baru dalam sistem.      
Long-term scheduler      mengontrol      
degree of multiprogramming      (jumlah proses dalam memori). Jika      
degree of multiprogramming      stabil, maka tingkat rata-rata penciptaan proses harus sama     dengan tingkat rata rata proses meninggalkan sistem. Maka dari     itu      
long-term scheduler      mungkin dipanggil hanya ketika suatu proses meninggalkan     sistem. Karena interval yang lebih panjang antara eksekusi,      
long-term scheduler      dapat menggunakan waktu yang lebih lama untuk menentukan proses     mana yang harus dipilih untuk dieksekusi.
Sangat penting bagi      
long-term scheduler      membuat seleksi yang hati-hati. Secara umum, proses dapat     dibedakan atas dua macam, yaitu proses      
      I/O bound           dan proses      
      CPU bound           . Proses      
I/O bound      adalah proses yang lebih banyak menghabiskan waktunya untuk     mengerjakan I/O dari pada melakukan komputasi. Proses      
CPU-bound      , di sisi lain, jarang melakukan permintaan I/O, dan     menggunakan lebih banyak waktunya untuk melakukan komputasi.     Oleh karena itu,      
long-term scheduler      harus memilih gabungan proses yang baik antara proses      
I/O bound      dan      
CPU bound      . Jika seluruh proses adalah      
I/O bound      ,      
ready queue      akan hampir selalu kosong, dan      
short-term scheduler      akan memiliki sedikit tugas. Jika seluruh proses adalah      
CPU bound      ,      
I/O waiting queue      akan hampir selalu kosong, peralatan akan tidak terpakai, dan     sistem akan menjadi tidak seimbang.Sistem dengan kinerja yang     terbaik akan memiliki kombinasi yang baik antara proses      
CPU bound      dan      
I/O bound      .
Pada sebagian sistem,      
long-term scheduler      bisa jadi tidak ada atau kerjanya sangat minim. Sebagai contoh,     sistem      
time-sharing      seperti UNIX sering kali tidak memiliki      
long-term scheduler      . Stabilitas sistem-sistem seperti ini bergantung pada     keterbatasan fisik (seperti jumlah terminal yang ada) atau pada     penyesuaian sendiri secara alamiah oleh manusia sebagai     pengguna. Jika kinerja menurun pada tingkat yang tidak dapat     diterima, sebagian pengguna akan berhenti.
Sebagian sistem operasi, seperti sistem      
time-sharing      , dapat memperkenalkan sebuah      
scheduler      tambahan, yaitu      
      medium-term scheduler           .      
Scheduler      ini digambarkan pada 
Gambar 3-6. Ide utama atau   kunci dari 
scheduler      ini terkadang akan menguntungkan untuk memindahkan proses dari     memori (dan dari pengisian aktif dari CPU), dan akibatnya      
degree of multiprogramming      akan berkurang. Di kemudian waktu, proses dapat dibawa kembali     dalam memori dan eksekusinya dapat dilanjutkan pada keadaan     dimana proses itu dipindahkan tadi. Skema ini disebut      
swapping      . Proses di-      
swapped out      dan di-      
swapped in      oleh      
scheduler      ini.      
Swapping      mungkin diperlukan untuk meningkatkan mutu penggabungan proses,     atau karena perubahan dalam kebutuhan memori yang mengakibatkan     memori harus dibebaskan.      
Swapping      dibahas dalam 
bagian berjudul Penukaran di Bab 5.
Mengganti CPU ke proses lain memerlukan penyimpanan keadaan     dari proses lama dan mengambil keadaan dari proses yang baru. Hal ini  dikenal dengan sebutan      
      context switch           .      
Context switch      sebuah proses direpresentasikan dalam PCB dari suatu proses;     termasuk nilai dari CPU register, status proses (bisa dilihat     pada 
Gambar 3-7)dan informasi manajemen memori.   Ketika      
context switch      terjadi,      
kernel           menyimpan data dari proses lama ke dalam PCB     nya dan mengambil data dari proses baru yang telah terjadwal     untuk berjalan. Waktu      
context switch      adalah murni      
overhead      , karena sistem melakukan pekerjaan yang tidak begitu berarti     selama melakukan pengalihan. Kecepatannya bervariasi dari mesin     ke mesin, bergantung pada kecepatan memori, jumlah register     yang harus di-copy, dan ada tidaknya instruksi khusus (seperti     instruksi tunggal untuk mengisi atau menyimpan seluruh     register). Tingkat kecepatan umumnya berkisar antara 1 sampai     1000 mikro detik.
Waktu      
context switch      sangat begantung pada dukungan perangkat keras. Sebagai contoh,     prosesor seperti UltraSPARC menyediakan beberapa set register.     Sebuah proses      
context switch      hanya memasukkan perubahan      
pointer           ke set register yang ada saat itu. Tentu saja, jika proses aktif      yang ada lebih banyak daripada proses yang ada pada set register,      sistem menggunakan bantuan untuk meng-copy data register dari dan      ke memori, sebagaimana sebelumnya. Semakin kompleks suatu sistem      operasi, semakin banyak pekerjaan yang harus dilakukan selama      
context switch      . Bisa dilihat pada Bab Memori, teknik managemen memori tingkat     lanjut dapat mensyaratkan data tambahan untuk diganti dengan     tiap data. Sebagai contoh, ruang alamat dari proses yang ada     saat itu harus dijaga sebagai ruang alamat untuk proses yang     akan dikerjakan berikutnya. Bagaimana ruang alamat dijaga,     berapa banyak pekerjaan dibutuhkan untuk menjaganya, tergantung     pada metode managemen memori dari sistem operasi. Akan kita     lihat pada Bab Memori,      
context switch      terkadang bisa menyebabkan      
bottleneck      , dan programmer menggunakan struktur baru (threads) untuk     menghindarinya kapan pun memungkinkan.
 
Proses yang dijalankan pada suatu sistem operasi dapat   bekerja secara bersama-sama ataupun sendiri saja. Bagian     sebelum ini telah menjelaskan mengenai konsep proses dan   bagaimana penjadwalan proses itu. Disini kita akan melihat    bagaimana hubungan antara proses-proses itu.
Proses yang bersifat      
concurrent      bekerja sama dengan proses lain. Proses itu kooperatif jika     mereka dapat saling mempengaruhi. Kerja sama antar proses itu     penting karena beberapa alasan :      
- Pembagian informasi : Beberapa proses dapat mengakses         beberapa data yang sama.
 
- Kecepatan komputasi : Tugas yang dijalankan dapat         berjalan dengan lebih cepat jika tugas tersebut         dipecah-pecah menjadi beberapa sub bagian dan dieksekusi         secara paralel dengan sub bagian yang lain. Peningkatan         kecepatan ini dapat dilakukan jika komputer tersebut         mempunyai beberapa elemen pemrosesan, seperti CPU atau         jalur I/O.
 
- Modularitas : Akan lebih mudah untuk mengatur tugas         yang kompleks jika tugas tersebut dipecah menjadi beberapa    sub bagian, kemudian mempunyai proses atau   thread    yang berbeda untuk menjalankan setiap sub bagian.
 
- Kenyamanan :          User          bisa dengan mudah mengerjakan sesuatu yang berbeda dalam         waktu yang sama. Contohnya satu          user          dapat mengetik, mengedit, dan mencetak suatu halaman         tertentu secara bersamaan.
 
Kerja sama antar proses membutuhkan suatu mekanisme yang     memperbolehkan proses-proses untuk mengkomunikasikan data     dengan yang lain dan meng-     
synchronize      kerja mereka sehingga tidak ada yang saling menghalangi. Salah     satu cara proses dapat saling berkomunikasi adalah      
Interprocess Communication      (IPC) yang akan dijelaskan lebih lanjut di bagian berikut.
Produser membuat suatu informasi yang dapat dibagi dengan     proses lainnya. Konsumer menghabiskan data yang dibuat oleh     produser. Misalnya program cetak memproduksi karakter yang     dipakai oleh   
printer  .
Masalah yang biasanya dihadapi oleh produser dan konsumer     adalah bagaimana caranya mensinkronisasikan kerja mereka     sehingga tidak ada yang saling mengganggu. Salah satu contoh     bagaimana masalah ini dapat terjadi adalah      
Bounded Buffer Problem      .
Solusi pembagian memori untuk      
Bounded Buffer Problem      diterangkan dengan program sebagai berikut :
import java.util.*;
public class BoundedBuffer {
    public BoundedBuffer() {
        // buffer diinisialisasikan kosong
        count   = 0;
        in      = 0;
        out     = 0;
        buffer = new Object[BUFFER_SIZE];
    }
    // produser memanggil method ini
    public void enter( Object item ) {
        while ( count == BUFFER_SIZE )
        ; // tidak melakukan apa-apa
        // menambahkan suatu item ke dalam buffer
        ++count;
        buffer[in]  = item;
        in  = ( in + 1 ) % BUFFER_SIZE;
        if ( count == BUFFER_SIZE )
            System.out.println( "Producer Entered " +
            item + " Buffer FULL" );
        else
            System.out.println( "Producer Entered " +
            item + " Buffer Size = " + count );
    }
    // konsumer memanggil method ini  
    public Object remove() {
        Object item ;
        while ( count == 0 )
        ; // tidak melakukan apa-apa
    
        // menyingkirkan suatu item dari buffer
        --count;
        item  = buffer[out];
        out   = ( out + 1 ) % BUFFER_SIZE;
        if ( count == 0 )
        System.out.println( "Consumer consumed " +
        item + " Buffer EMPTY" );
        else
        System.out.println( "Consumer consumed " +
        item + " Buffer Size = " +count );
        return item;
    }
    public static final int NAP_TIME = 5;
    private static final int BUFFER_SIZE = 5;
    private volatile int count;
    private int in;     // arahkan ke posisi kosong selanjutnya
    private int out;        // arahkan ke posisi penuh selanjutnya
    private Object[] buffer;
}
     | 
Buffer      adalah tempat penyimpanan data dimana produser mengisinya dan     konsumer mengosongkan      
buffer      tersebut. Jika      
buffer      kosong, konsumer harus menunggu, dan ketika      
buffer      penuh, produser harus menunggu. Disinilah produser harus     bekerja sama dengan konsumer. Konsumer harus menunggu sampai     ada barang yang diproduksi.
Program dibawah ini menggambarkan proses yang dijalankan     oleh produser untuk      
Bounded Buffer Problem     
//Producer.java
import java.util.*;
public class Producer extends Thread {
    public Producer(BoundedBuffer b) {
        buffer = b;
    }
    public void run() {
        Date message;
        while (true) {
           int sleeptime = 
             (int) (BoundedBuffer.NAP_TIME * Math.random() );
           System.out.println("Producer sleeping for " 
             + sleeptime + " seconds");
       
           try { sleep(sleeptime*1000); } 
           catch(InterruptedException e) {}
           // membuat suatu barang & memasukkannya ke buffer
           message = new Date();      
           System.out.println("Producer produced " + message);
           buffer.enter(message);
       }
    }
    private  BoundedBuffer buffer;
}
     | 
Program berikut menggambarkan proses yang dijalankan oleh     konsumer pada      
Bounded Buffer Problem     
// Consumer.java
 
import java.util.*;
public class Consumer extends Thread {
    public Consumer(BoundedBuffer b) {
       buffer = b;
    }
    public void run() {
       Date message;
       while (true) {
          int sleeptime = 
            (int) (BoundedBuffer.NAP_TIME * Math.random() );
          System.out.println("Consumer sleeping for " 
            + sleeptime + " seconds");
 
          try { sleep(sleeptime*1000); } 
          catch(InterruptedException e) {}
     
          // mengambil barang dari buffer
          System.out.println("Consumer wants to consume.");
          message = (Date)buffer.remove();
       }
    }  
   
    private  BoundedBuffer buffer;}
     | 
Masalah produser-konsumer dengan      
unbounded-buffer      tidak menempatkan batas praktikal pada ukuran pada      
buffer      . Konsumer harus menunggu untuk barang baru, tetapi produser     dapat selalu memproduksi barang baru. Sedangkan masalah     produser-konsumer      
bounded-buffer      mengasumsikan ukuran      
buffer      yang ditetapkan. Pada kasus ini, konsumer harus menunggu sampai          
buffer      kosong dan produser harus menunggu sampai      
buffer      penuh.
Sebelumnya kita telah ketahui seluk beluk dari suatu proses   mulai dari pengertiannya, cara kerjanya, sampai   operasi-operasinya seperti proses pembentukannya dan proses   pemberhentiannya setelah selesai melakukan eksekusi. Kali ini   kita akan mengulas bagaimana hubungan antar proses dapat   berlangsung, misal bagaimana beberapa proses dapat saling   berkomunikasi dan bekerja-sama.
Kalau pada sub-bab sebelumnya kita banyak membahas mengenai   buffer, dan lingkungan yang berbagi memori. Pada bagian ini kita    lebih banyak membahas teknik komunikasi antara proses melalui    kirim(
send) dan terima    (
recive) yang biasa dikenal sebagai    IPC.
Selain itu pada bagian ini kita akan menyingung sedikit   mengenai client/server proses. Beberapa topik yang akan dibahas   adalah Java RMI (Remote Method Invocation) dan RPC (Remote   Procedure Call). Yang keduanya juga menggunakan mekanisme   komunikasi IPC, namun menggunkan sistem yang terdistribusi yang   melibatkan jaringan. Pada bagian ini juga akan dibahas mengenai    infrastruktur dasar jaringan yaitu socket.   
Proses yang bersifat simultan        (
concurrent) dijalankan       pada sistem operasi dapat dibedakaan menjadi yaitu proses       independen dan proses kooperatif. Suatu proses dikatakan       independen apabila proses tersebut tidak dapat terpengaruh       atau dipengaruhi oleh proses lain yang sedang dijalankan pada       sistem. Berarti, semua proses yang tidak membagi data apa pun       (baik sementara/ tetap) dengan proses lain adalah       independent. Sedangkan proses kooperatif adalah proses yang       dapat dipengaruhi atau pun terpengaruhi oleh proses lain yang       sedang dijalankan dalam sistem. Dengan kata lain, proses       dikatakan kooperatif bila proses dapat membagi datanya dengan       proses lain.
Ada 4 alasan untuk penyediaan sebuah lingkungan yang       memperbolehkan terjadinya proses kooperatif :
- Pembagian informasi : apabila beberapa pengguna             dapat tertarik pada bagian informasi yang sama (sebagai             contoh, sebuah berkas bersama), kita harus menyediakan             sebuah lingkungan yang mengijinkan akses secara terus             menerus ke tipe dari sumber-sumber tersebut.
 
- Kecepatan penghitungan / komputasi : jika kita             menginginkan sebuah tugas khusus untuk menjalankan             lebih cepat, kita harus membagi hal tersebut ke dalam             subtask, setiap bagian dari subtask akan dijalankan             secara parallel dengan yang lainnya. Peningkatan             kecepatan dapat dilakukan hanya jika komputer tersebut             memiliki elemen-elemen pemrosesan ganda (seperti CPU             atau jalur I/O).
 
- Modularitas : kita mungkin ingin untuk membangun             sebuah sistem pada sebuah model modular-modular,             membagi fungsi sistem menjadi beberapa proses atau             threads.
 
- Kenyamanan : bahkan seorang pengguna individu             mungkin memiliki banyak tugas untuk dikerjakan secara             bersamaan pada satu waktu. Sebagai contoh, seorang             pengguna dapat mengedit, memcetak, dan meng-compile             secara parallel.
 
import java.util.*;
public class BoundedBuffer {
    public BoundedBuffer() {
        // buffer diinisialisasikan kosong
        count   = 0;
        in      = 0;
        out     = 0;
        buffer = new Object[BUFFER_SIZE];
     }
     // produser memanggil method ini
     public void enter( Object item ) {
        while ( count == BUFFER_SIZE )
            ; // do nothing
        // menambahkan suatu item ke dalam buffer
        ++count;
        buffer[in]  = item;
        in  = ( in + 1 ) % BUFFER_SIZE;
        if ( count == BUFFER_SIZE )
            System.out.println( "Producer Entered " +
                item + " Buffer FULL" );
        else
            System.out.println( "Producer Entered " +
                item + " Buffer Size = " + count );
    }
    // consumer memanggil method ini  
    public Object remove() {
        Object item ;
        while ( count == 0 )
            ; // do nothing
        // menyingkirkan suatu item dari buffer
        --count;
        item  = buffer[out];
        out   = ( out + 1 ) % BUFFER_SIZE;
        if ( count == 0 )
            System.out.println( "Consumer consumed " +
              item + " Buffer EMPTY" );
        else
            System.out.println( "Consumer consumed " +
              item + " Buffer Size = " +count );
        return item;
    }
    public static final int NAP_TIME = 5;
    private static final int BUFFER_SIZE = 5;
    private volatile int count;
    private int in; // arahkan ke posisi kosong selanjutnya
    private int out;    // arahkan ke posisi penuh selanjutnya
    private Object[] buffer;
}
         | 
Sebuah produsen proses membentuk informasi yang dapat       digunakan oleh konsumen proses. Sebagai contoh sebuah cetakan       program yang membuat banyak karakter yang diterima oleh       driver pencetak. Untuk memperbolehkan produser dan konsumer       proses agar dapat berjalan secara terus menerus, kita harus       menyediakan sebuah item buffer yang dapat diisi dengan proses       produser dan dikosongkan oleh proses konsumer. Proses       produser dapat memproduksi sebuah item ketika konsumer sedang       mengkonsumsi item yang lain. Produser dan konsumer harus       dapat selaras. Konsumer harus menunggu hingga sebuah item       diproduksi.
Cara lain untuk meningkatkan efek yang sama adalah       untuk sistem operasi yaitu untuk menyediakan alat-alat proses       kooperatif untuk berkomunikasi dengan yang lain lewat sebuah       komunikasi dalam proses IPC (Inter-Process Communication).       IPC menyediakan sebuah mekanisme untuk megijinkan       proses-proses untuk berkomunikasi dan menyelaraskan aksi-aksi       mereka tanpa berbagi ruang alamat yang sama. IPC adalah       khusus digunakan dalam sebuah lingkungan yang terdistribusi       dimana proses komunikasi tersebut mungkin saja tetap ada       dalam komputer-komputer yang berbeda yang tersambung dalam       sebuah jaringan. IPC adalah penyedia layanan terbaik dengan       menggnakan sebuah sistem penyampaian pesan, dan sistem-sistem       pesan dapat diberikan dalam banyak cara.
Fungsi dari sebuah sistem pesan adalah untuk         memperbolehkan komunikasi satu dengan yang lain tanpa perlu         menggunakan pembagian data. Sebuah fasilitas IPC         menyediakan paling sedikit 2 operasi yaitu kirim (pesan)         dan terima (pesan). Pesan dikirim dengan sebuah proses yang         dapat dilakukan pada ukuran pasti atau variabel. Jika hanya         pesan dengan ukuran pasti dapat dikirimkan, level sistem         implementasi adalah sistem yang sederhana. Pesan berukuran         variabel menyediakan sistem implementasi level yang lebih         kompleks.
Jika dua buah proses ingin berkomonikasi, misalnya         proses P dan proses Q, mereka harus mengirim pesan atau         menirima pesan dari satu ke yang lainnya. Jalur ini dapat         diimplentasikan dengan banyak cara, namun kita hanya akan         memfokuskan pada implementasi logiknya saja, bukan         implementasi fisik(seperti shared memory, hardware bus,         atau jaringan).Berikut ini ada beberapa metode untuk         mengimplementasikan sebuah jaringan dan operasi pengiriman         / penerimaan secara logika :
- Komunikasi langsung atau tidak langsung.
 
- Komunikasi secara simetris / asimetris.
 
- Buffer otomatis atau eksplisit.
 
- Pengiriman berdasarkan salinan atau               referensi.
 
- Pesan berukuran pasti dan variabel.
 
Proses-proses yang ingin dikomunikasikan harus         memiliki sebuah cara untuk memilih satu dengan yang lain.         Mereka dapat menggunakan komunikasi langsung / tidak         langsung.
Setiap proses yang ingin berkomunikasi harus           memiliki nama yang bersifat eksplisit baik penerimaan           atau pengirim dari komunikasi tersebut. Dalam konteks           ini, pengiriman dan penerimaan pesan secara primitive           dapat dijabarkan sebagai :
- Send (P, message) - mengirim sebuah pesan ke                 proses P.
 
- Receive (Q, message) - menerima sebuah pesan                 dari proses Q.
 
Sebuah jaringan komunikasi pada bahasan ini           memiliki beberapa sifat, yaitu :
- Sebuah jaringan yang didirikan secara                 otomatis diantara setiap pasang dari proses yang                 ingin dikomunikasikan. Proses tersebut harus                 mengetahui identitas dari semua yang ingin                 dikomunikasikan.
 
- Sebuah jaringan adalah terdiri dari                 penggabungan 2 proses.
 
- Diantara setiap pesan dari proses terdapat                 tepat sebuah jaringan.
 
Pembahasan ini memperlihatkan sebuah cara simetris           dalam pemberian alamat. Oleh karena itu, baik keduanya           yaitu pengirim dan penerima proses harus memberi nama           bagi yang lain untuk berkomunikasi, hanya pengirim yang           memberikan nama bagi penerima sedangkan penerima tidak           menyediakan nama bagi pengirim. Dalam konteks ini,           pengirim dan penerima secara sederhana dapat dijabarkan           sebagai :
- Send (P, message) - mengirim sebuah pesan                 kepada proses P.
 
- Receive (id, message) - menerima sebuah pesan                 dari semua proses. Variabel id diatur sebagai nama                 dari proses dengan komunikasi.
 
Kerugian dari kedua cara yang disebutkan diatas           adalah adanya kebatasan modularitas, merubah nama proses           mungkin mengharuskan kita untuk merubah semua definisi           proses yang lain. Semua referensi kepada nama yang lama           harus ditemukan.
Dengan komunikasi tidak langsung, pesan akan           dikirimkan pada dan diterima dari / melalui mailbox           (Kotak Surat) atau terminal-terminal, sebuah mailbox           dapat dilihat secara abstrak sebagai sebuah objek didalam           setiap pesan yang dapat ditempatkan dari proses dan dari           setipap pesan yang bias dipindahkan. Setiap kotak surat           memiliki sebuah identifikasi (identitas) yang unik,           sebuah proses dapat berkomunikasi dengan beberapa proses           lain melalui sebuah nomor dari mailbox yang berbeda. Dua           proses dapat saling berkomunikasi apabila kedua proses           tersebut sharing mailbox. Pengirim dan penerima dapat           dijabarkan sebagai :
- Send (A, message) - mengirim pesan ke mailbox                 A.
 
- Receive (A, message) - menerima pesan dari                 mailbox A.
 
Dalam masalah ini, link komunikasi mempunyai sifat           sebagai berikut :
- Sebuah link dibangun diantara sepasang proses                 dimana kedua proses tersebut membagi                 mailbox.
 
- Sebuah link mungkin dapat berasosiasi dengan                 lebih dari 2 proses.
 
- Diantara setiap pasang proses komunikasi,                 mungkin terdapat link yang berbeda-beda, dimana                 setiap link berhubungan pada satu mailbox.
 
Misalkan terdapat proses P1, P2 dan P3 yang           semuanya share mailbox. Proses P1 mengirim pesan ke A,           ketika P2 dan P3 masing-masing mengeksekusi sebuah           kiriman dari A. Proses mana yang akan menerima pesan yang           dikirim P1?. Jawabannya tergantung dari jalur yang kita           pilih :
- Mengijinkan sebuah link berasosiasi dengan                 paling banyak 2 proses.
 
- Mengijinkan paling banyak 1 proses pada suatu                 waktu untuk mengeksekusi hasil kiriman (receive                 operation).
 
- Mengijinkan sistem untuk memilih secara                 mutlak proses mana yang akan menerima pesan (apakah                 itu P2 atau P3 tetapi tidak keduanya, tidak akan                 menerima pesan). Sistem mungkin mengidentifikasi                 penerima kepada pengirim.
 
Mailbox mungkin dapat dimiliki oleh sebuah proses           atau sistem operasi. Jika mailbox dimiliki oleh proses,           maka kita mendefinisikan antara pemilik (yang hanya dapat           menerima pesan melalui mailbox) dan pengguna dari mailbox           (yang hanya dapat mengirim pesan ke mailbox). Selama           setiap mailbox mempunyai kepemilikan yang unik, maka           tidak akan ada kebingungan tentang siapa yang harus           menerima pesan dari mailbox. Ketika proses yang memiliki           mailbox tersebut diterminasi, mailbox akan hilang. Semua           proses yang mengirim pesan ke mailbox ini diberi pesan           bahwa mailbox tersebut tidak lagi ada.
Dengan kata lain, mempunyai mailbox sendiri yang           independent, dan tidak melibatkan proses yang lain. Maka           sistem operasi harus memiliki mekanisme yang mengijinkan           proses untuk melakukan hal-hal dibawah ini :
- Membuat mailbox baru.
 
- Mengirim dan menerima pesan melalui               mailbox.
 
- Menghapus mailbox.
 
Proses yang membuat mailbox pertama kali secara           default akan memiliki mailbox tersebut. Untuk pertama           kali, pemilik adalah satu-satunya proses yang dapat           menerima pesan melalui mailbox ini. Bagaimanapun,           kepemilikan dan hak menerima pesan mungkin dapat           dialihkan ke proses lain melalui sistem           pemanggilan.
Komunikasi antara proses membutuhkan place by calls       untuk mengirim dan menerima data primitive. Terdapat design       yang berbeda-beda dalam implementasi setiap primitive.       Pengiriman pesan mungkin dapat diblok (blocking) atau tidak       dapat dibloking (nonblocking) - juga dikenal dengan nama       sinkron atau asinkron.
- Pengiriman yang diblok : Proses pengiriman di             blok sampai pesan diterima oleh proses penerima             (receiving process) atau oleh mailbox.
 
- Pengiriman yang tidak diblok : Proses pengiriman             pesan dan mengkalkulasi operasi.
 
- Penerimaan yang diblok : Penerima mem blok             samapai pesan tersedia.
 
- Penerimaan yang tidak diblok : Penerima             mengembalikan pesan valid atau null.
 
Baik komunikasi itu langsung atau tak langsung,       penukaran pesan oleh proses memerlukan antrian sementara.       Pada dasarnya, terdapat tiga jalan dimana antrian tersebut       diimplementasikan :
- Kapasitas nol: antrian mempunyai panjang maksimum             0, maka link tidak dapat mempunyai penungguan pesan             (message waiting). Dalam kasus ini, pengirim harus             memblok sampai penerima menerima pesan.
 
- Kapasitas terbatas: antrian mempunyai panjang             yang telah ditentukan, paling banyak n pesan dapat             dimasukkan. Jika antrian tidak penuh ketika pesan             dikirimkan, pesan yang baru akan menimpa, dan pengirim             pengirim dapat melanjutkan eksekusi tanpa menunggu.             Link mempunyai kapasitas terbatas. Jika link penuh,             pengirim harus memblok sampai terdapat ruang pada             antrian.
 
- Kapasitas tak terbatas: antrian mempunyai panjang             yang tak terhingga, maka, semua pesan dapat menunggu             disini. Pengirim tidak akan pernah di blok.
 
Sekarang kita mempunyai solusi problem       produser-konsumer yang menggunakan penyampaian pesan.       Produser dan konsumer akan berkomunikasi secara tidak       langsung menggunakan mailbox yang dibagi. Buffer menggunakan       java.util.Vector class sehingga buffer mempunyai kapasitas       tak terhingga. Dan send() dan read() method adalah       nonblocking. Ketika produser memproduksi suatu item, item       tersebut diletakkan ke mailbox melalui send() method.       Konsumer menerima item dari mailbox menggunakan receive()       method. Karena receive() nonblocking, consumer harus       mengevaluasi nilai dari Object yang direturn dari receive().       Jika null, mailbox kosong.
import java.util.*;
    
    public class Producer extends Thread {
        private MessageQueueueue mbox;
        public Producer( MessageQueueueue m ) {
            mbox  = m;
        }
        public void run() {
            Date message;
            while ( true ) {
                int sleeptime   = ( int ) ( Server.NAP_TIME * Math.random() );
                System.out.println( "Producer sleeping for " + sleeptime + " seconds" );
                try {
                    Thread.sleep(sleeptime*1000);
                } catch( InterruptedException e ) {}
                message = new Date();
                System.out.println( "Producer produced " + message );
                mbox.send( message );
            }
        }
    }
       | 
import java.util.*;
    
    public class Consumer extends Thread {
        private MessageQueueueue mbox;
        public Consumer( MessageQueueueue m ) {
            mbox  = m;
    }
        
    public void run() {
        Date message;
        while ( true ) {
            int sleeptime = ( int ) ( Server.NAP_TIME * Math.random());
            System.out.println("Consumer sleeping for " + sleeptime + " seconds" );
            try {
                Thread.sleep( sleeptime * 1000 );
            } catch( InterruptedException e ) {}
            message = ( Date ) mbox.receive();
            if ( message != null )
                System.out.println("Consumer consume " + message );
            }
        }
    }
       | 
Kita memiliki dua aktor di sini, yaitu Produser dan       Konsumer. Produser adalah thread yang menghasilkan waktu       (Date) kemudian menyimpannya ke dalam antrian pesan. Produser       juga mencetak waktu tersebut di layer (sebagai umpan balik       bagi kita). Konsumer adalah thread yang akan mengakses       antrian pesan untuk mendapatkan waktu (date) itu dan tak lupa       mencetaknya di layer. Kita menginginkan supaya konsumer itu       mendapatkan waktu sesuatu dengan urutan sebagaimana produser       menyimpan waktu tersebut. Kita akan menghadapi salah satu       dari dua kemungkinan situasi di bawah ini :
- Bila p1 lebih cepat dari c1, kita akan memperoleh             output sebagai berikut :
. . .
Consumer consume Wed May 07 14:11:12 ICT 2003
Consumer sleeping for 3 seconds
Producer produced Wed May 07 14:11:16 ICT 2003
Producer sleeping for 4 seconds
// p1 sudah mengupdate isi mailbox waktu dari Wed May 07 
// 14:11:16 ICT 2003 ke Wed May 07 14:11:17 ICT 2003,   
// padahal c1 belum lagi mengambil waktu Wed May 07 14:11:16
Producer produced Wed May 07 14:11:17 ICT 2003
Producer sleeping for 4 seconds
Consumer consume Wed May 07 14:11:17 ICT 2003
Consumer sleeping for 4 seconds  
// Konsumer melewatkan waktu Wed May 07 14:11:16
. . .
               | 
 
- Bila p1 lebih lambat dari c1, kita akan             memperoleh keluaran seperti berikut :
. . .
Producer produced Wed May 07 14:11:11 ICT 2003
Producer sleeping for 1 seconds
Consumer consume Wed May 07 14:11:11 ICT 2003
Consumer sleeping for 0 seconds
// c1 sudah mengambil isi dari mailbox, padahal p1 belum 
// lagi megupdate isi dari mailbox dari May 07 14:11:11
// ICT 2003 ke May 07 14:11:12 ICT 2003, c1 mendapatkan 
// waktu Wed May 07 14:11:11 ICT 2003 dua kali.
Consumer consume Wed May 07 14:11:11 ICT 2003
Consumer sleeping for 0 seconds
Producer sleeping for 0 seconds
Producer produced Wed May 07 14:11:12 ICT 2003 
. . .
               | 
 
Situasi di atas dikenal dengan race conditions. Kita       dapat menghindari situasi itu dengan mensinkronisasikan       aktivitas p1 dan c1 (sehubungan dengan akses mereka ke       mailbox. Proses tersebut akan didiskusikan pada chapter yang       akan datang (chapter 5).
import java.util.*;
public class MessageQueue {
    private Vector q;
    public MessageQueue() {
        q = new Vector();
    }
    
    // Mengimplementasikan pengiriman nonblocking
    public void send( Object item ) {
        q.addElement( item );
    }
    
    // Mengimplementasikan penerimaan nonblocking
    public Object receive() {
        Object item;
        if ( q.size() == 0 ) {
            return null;
        }
        else {
            item = q.firstElement();
            q.removeElementAt(0);
            return item;
        }
    }
}
       | 
- Menunggu sampai batas waktu yang tidak dapat             ditentukan sampai terdapat ruang kosong pada             mailbox.
 
- Menunggu paling banyak n milidetik.
 
- Tidak menunggu, tetapi kembali (return)             secepatnya.
 
- Satu pesan dapat diberikan kepada sistem operasi             untuk disimpan, walaupun mailbox yang dituju penuh.             Ketika pesan dapat disimpan pada mailbox, pesan akan             dikembalikan kepada pengirim(sender). Hanya satu pesan             kepada mailbox yang penuh yang dapat diundur (pending)             pada suatu waktu untuk diberikan kepada thread             pengirim.
 
Dengan makin berkembangnya teknologi jaringan komputer,     sekarang ini ada kecenderungan sebuah sistem yang bekerja sama     menggunakan jaringan. Dalam topik ini akan kita bahas beberapa     metoda komunikasi antar proses yang melibatkan jaringan     komputer.
Socket adalah sebuah endpoint untuk komunikasi didalam       jaringan. Sepasang proses atau thread berkomunikasi dengan       membangun sepasang socket, yang masing-masing proses       memilikinya. Socket dibuat dengan menyambungkan dua buah IP       Address melalui port tertentu. Secara umum socket digunakan       dalam client/server system, dimana sebuah server akan       menunggu client pada port tertentu. Begitu ada client yang       mengkontak server maka server akan menyetujui komunikasi       dengan client melalui socket yang dibangun.
Pada umumnya sebuah server melayani client secara         konkuren, oleh sebab itu dibutuhkan thread yang         masing-masing thread melayani clientnya masing-masing. Jadi         server akan membentuk thread baru begitu ada koneksi dari         client yang diterima (accept)
Server menggunakan thread apabila client melakukan     koneksi, sehingga server memiliki tingkat reabilitas yang     tinggi. Pada sistem yang memiliki banyak pemakai sekaligus      thread mutlak dibutuhkan, karena setiap pemakai sistem      pasti menginginkan respon yang baik dari server.
Java menyediakan dua buah tipe socket yang berbeda dan     sebuah socket spesial. Semua soket ini tersedia dalam paket     jaringan, yang merupakan paket standar java. Berikut ini soket     yang disediakan oleh java :   
- Connection-Oriented (TCP) socket, yang     diimplementasikan pada kelas     java.net.Socket       
 
- Connectionless Socket (UDP), yang diimplentasikan     oleh kelas     java.net.DatagramSocket
 
- Dan yang terakhir adalah     java.net.MulticastSocket,     yang merupakan perluasan (extended) dari Socket UDP. Tipe      socket ini memiliki kemampuan untuk mengirim pesan kebanyak     client sekaligus (Multicast), sehingga baik digunakan pada      sistem yang memiliki jenis layanan yang sama.
 
...
public WebServer(int port, String docRoot) throws IOException
{
 this.docRoot =  new File(docRoot);
 if(!this.docRoot.isDirectory())
 {
  throw new IOException(docRoot + " bukan direktori.");
 }
 System.out.println("Menghidupkan Web server ");
 System.out.println("port : " + port);
 System.out.println("docRoot : " + docRoot);
 try
 {
  serverSocket = new ServerSocket(port);
 }
 catch(IOException ioe)
 {
  System.out.println("Port sudah digunakan");
  System.exit(1);
 }
}
                                                                                                                             
                                                                                                                             
public void run()
{
 while(true)
 {
  try{
   System.out.println("Menanti connection ... ");
   Socket socket = serverSocket.accept();
   String alamatClient = socket.getInetAddress().getHostAddress();
                                                                                                                             
   System.out.println("Menangkap connection dari " + alamatClient);
   InputStream inputStream = socket.getInputStream();
   InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
   BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                                                                                                                             
   OutputStream outputStream = socket.getOutputStream();
   ... 
         | 
Potongan kode diatas memperlihatkan teknik yang          digunakan oleh java untuk membuka socket (pada kasus ini          server socket). Selanjutnya server dapat berkomunikasi           dengan clientnya menggunakan InputStream untuk menerima          pesan dan OutputStream untuk mengirim pesan.
Remote Procedure Call (RPC) adalah sebuah metoda yang         memungkinkan kita untuk mengakses sebuah prosedur yang         berada di komputer lain. Untuk bisa melakukan ini sebuah         komputer (server) harus menyediakan layanan remote         prosedur. Pendekatan yang dilakuan adalah, sebuah server         membuka socket, menunggu client yang meminta proseduryang         disediakan oleh server.
Remote Procedure Call masih menggunakan cara         primitive dalam pemrograman, yaitu menggunakan paradigma         procedural programming. Hal itu membuat kita sulit ketika         menyediakan banyak remote procedure.
RPC menggunakan soket untuk berkomunikasi dengan      proses lainnya. Pada beberapa sistem (Seperti SUN) RPC      secara default sudah terinstall kedalam sistemnya,      biasanya RPC ini digunakan untuk administrasi sistem.      Sehingga seorang administrator jaringan bisa mengakses      sistemnya dan memanajemen sistemnya dari mana saja,      selama sistemnya terhubung kejaringan.
Pendekatan kedua yang akan kita bahas adalah         RMI (Remote Method Invocation), sebuah teknik pemanggilan         method remote yang lebih secara umum lebih baik daripada          RPC. RMI menggunakan paradigma pemrograman berorientasi          objek (OOP).Dengan RMI memungkinkan kita untuk mengirim objek         sebagai parameter dari remote method. Dengan dibolehkannya         program java memanggil method pada remote objek, RMI         membuat user dapat mengembangkan aplikasi java yang         terdistribusi pada jaringan
Untuk membuat remote method bisa diakses RMI         mengimplementasikan remote object menggukan stub dan         skleton. Stub bertindak sebagai proxy disisi client, yaitu         yang menghubungkan client dengan skleton yang berada disisi         server. Stub yang ada disisi client bertanggung jawab untuk         membungkus nama method yang akan diakses, dan parameternya,         hal ini biasa dikenal dengan marshalling. Stub mengirim         paket yang sudah dibungkus ini ke server dan akan di buka         (unmarshalling) oleh skleton. Skleton akan menerima hasil         keluaran yang telah diproses oleh method yang dituju, lalu         akan kembali dibungkus (marshal) dan dikirim kembali ke         client yang akan diterima oleh stub dan kembali dibuka         paketnya (unmarshall).
Untuk membuat remote objek kita harus           mendefinisikan semua method yang akan kita sediakan pada           jaringan, setelah itu dapat digunakan RMI compiler untuk           membuat stub dan skleton. Setelah itu kita harus           mem-binding remote objek yang kita sediakan kedalam           sebuah RMI registry. Setelah itu client dapat mengakses           semua remote method yang telah kita sediakan menggunkan           stub yang telah dicompile menggunakan RMI compiler           terebut.
Sekali objek didaftarkan ke server, client dapat           mengakses remote object dengan menjalankan           
Naming.lookup() method.       RMI menyediakan url untuk pengaksesan ke remote objek        yaitu 
rmi://host/objek,       dimana host adalah nama server tempat kita mendaftarkan           remote objek dan objek adalah parameter yang kita gunakan           ketika kita memanggil method       
Naming.rebind(). Client        juga harus menginstall RMISecurityManager untuk memastikan           keamanan client ketika membuka soket kejaringan.
Java memilki sistem security yang baik sehingga user        dapat lebih nyaman dalam melakukan komunikasi pada jaringan.       Selain itu java sudah mendukung pemorograman berorientasi       object, sehingga pengembangan software berskala besar sangat       dimungkinkan dilakukan oleh java. RMI sendiri merupakan       sistem terdistribusi yang dirancang oleh SUN pada platfrom       yang spesifik yaitu Java, apabila anda tertarik untuk       mengembangkan sistem terdistribusi yang lebih portable dapat       digunakan CORBA sebagai solusi alternatifnya.