Race Condition

Race condition adalah suatu kondisi dimana dua atau lebih proses mengakses shared memory/sumber daya pada saat yang bersamaan dan hasil akhir dari data tersebut tergantung dari proses mana yang terakhir selesai dieksekusi sehingga hasil akhirnya terkadang tidak sesuai dengan yang dikehendaki.

Contoh 18.1. Race Condition

         
 1.  int counter = 0;
 2.  //Proses yang dilakukan oleh produsen
 3.  item nextProduced;
 4.  while (1) {
 5.     while (counter == BUFFER_SIZE) { ... do nothing ... }
 6.     buffer[in] = nextProduced;
 7.     in = (in + 1) % BUFFER_SIZE;
 8.     counter++;
 9.  }
10. //Proses yang dilakukan oleh konsumen
11. item nextConsumed;
12. while (1) {
13.    while (counter == 0)            { ... do nothing ... }
14.    nextConsumed = buffer[out] ;
15.    out = (out + 1) % BUFFER_SIZE;
16.    counter--;
17. }


Pada program di atas, terlihat bahwa terdapat variabel counter yang diinisialisasi dengan nilai 0, dan ditambah 1 setiap kali terjadi produksi serta dikurangi 1 setiap kali terjadi konsumsi. Pada bahasa mesin, baris kode counter++ dan counter-- diimplementasikan seperti di bawah ini:

Contoh 18.2. Race Condition dalam bahasa mesin

        
//counter++
register1 = counter
register1 = register1 + 1
counter   = register1

//counter--
register2 = counter
register2 = register2 - 1
counter   = register2


Jika perintah counter++ dan counter-- berusaha mengakses nilai counter secara konkuren, maka nilai akhir dari counter bisa salah. Hal ini tidak berarti nilainya pasti salah, tapi ada kemungkinan untuk terjadi kesalahan. Contoh urutan eksekusi baris kode tersebut yang mengakibatkan kesalahan pada nilai akhir counter:

Contoh 18.3. Program yang memperlihatkan Race Condition

            2//misalkan nilai awal counter adalah 2
    1.produsen: register1 = counter       (register1 = 2)
    2.produsen: register1 = register1 + 1 (register1 = 3)
    3.konsumen: register2 = counter       (register2 = 2)
    4.konsumen: register2 = register2 - 1 (register2 = 1)
    5.konsumen: counter   = register2     (counter = 1)
    6.produsen: counter   = register1     (counter = 3)


Status akhir dari counter seharusnya adalah 0, tapi kalau urutan pengeksekusian program berjalan seperti di atas, maka hasil akhirnya menjadi 3. Perhatikan bahwa nilai akhir counter akan mengikuti eksekusi terakhir yang dilakukan oleh komputer. Pada program di atas, pilihannya bisa 1 atau 3. Perhatikan bahwa nilai dari counter akan bergantung dari perintah terakhir yang dieksekusi. Oleh karena itu maka kita membutuhkan sinkronisasi yang merupakan suatu upaya yang dilakukan agar proses-proses yang saling bekerjasama dieksekusi secara beraturan demi mencegah timbulnya suatu keadaan race condition.

Gambar 18.1. Ilustrasi program produsen dan konsumen

Ilustrasi program produsen dan konsumen

Kunci untuk mencegah masalah ini dan di situasi yang lain yang melibatkan memori bersama, berkas bersama, dan sumber daya lain yang digunakan secara bersama-sama adalah menemukan beberapa jalan untuk mencegah lebih dari satu proses melakukan proses tulis dan baca kepada data yang sama pada saat yang sama. Dengan kata lain, kita membutuhkan mutual exclusion, sebuah jalan yang menjamin jika sebuah proses sedang menggunakan variabel atau berkas yang digunakan bersama-sama, proses lain akan dikeluarkan dari pekerjaan yang sama.

Cara untuk menghindari race condition adalah kita harus dapat menjamin bahwa jika suatu proses sedang menjalankan critical section, maka proses lain tidak boleh masuk ke dalam critical section tersebut. Critical section dijelaskan dibawah.