Oh Tidak! Race Condition

Oh Tidak! Race Condition

Data jadi aneh karena terjadi perubahan yang tidak singkron

Race condition? Hmmm... Sudah pernah dengar istilah ini sebelumnya? Ini bukan arsitektur, bukan pattern, bukan juga ... Tapi ini adalah masalah yang terjadi saat kita mengelola data. Apa sih masalah race condition ini?

Yok kita gass...!

Ilustrasi

Pernah kah temen-temen mengubah nomor Whatsapp? Apa yang terjadi pada kontak yang lama? Mereka akan kesulitan menghubungi kita karena ternyata nomor WA kita sudah ganti.

Kondisi race condition kurang lebih mirip seperti itu. Satu sisi, penerima informasi sudah menerima data, lalu data tersebut berubah, kemudian data yang sudah didapatkan di awal, tak bisa digunakan lagi.

Apa itu race condition?

Race condition adalah situasi saat suatu data digunakan oleh banyak pihak tetapi tidak tersingkronisasi dengan baik sehingga data satu dengan yang lain bisa saja berbeda. Kalau yang di istilah koding, ini berarti ada banyak thread (process) yang mengakses memory yang sama, lalu tidak ada singkronisasi antar thread jika data tersebut sudah berubah.

Apa penyebab race condition?

Tidak adanya singkronisasi. Itu adalah penyebab utamanya. Seandainya banyak thread yang mengakses memory yang sama, tetapi ditambah singronisasi antar thread, tentu race condition dapat dihindari.

Apa akibat dari race condition?

Perubahan data tidak terkontrol sehingga menyebabkan output atau hasil dari pengolahan data yang kita inginkan, tidak sesuai harapan. Tentu ini berbahaya, terutama pada sistem keuangan, atau sistem vital lainnya.

Bagaimana mengatasi race condition?

Pertama, mari kita lihat kondisi race condition pada baris kode di bawah ini.

var money int = 0

func routine() {
    for i := 0; i < 1000000; i++ {
        money++
    }
}

func main() {
    wg := sync.WaitGroup{}
    wg.Add(3)
    go func() {
        defer wg.Done()
        routine()
    }()
    go func() {
        defer wg.Done()
        routine()
    }()
    wg.Wait()

    fmt.Println(money)
}

Contoh kode di atas menggunakan bahasa pemrograman Go, gak perlu fokus ke bahasanya, mari kita pahami aja apa yang sebetulnya terjadi. Karena ini bisa terjadi di bahasa pemrograman lainnya.

Yang terjadi pada kode di atas, terdapat variable dengan nama money yang awalnya memiliki nilai 0. Lalu terdapat fungsi routine yang menambah nilai money sebanyak 1000000 kali. Berikutnya, di situ kita jalankan fungsi routine secara konkuren sehingga terjadi 2 proses yang berbeda tetapi mengubah variable yang sama.

Oke, sebelum ke pokok masalah, kita ketahui dulu nilai money seharusnya berapa. Karena kita menjalankan fungsi routine 2 kali, seharusnya variable money nilainya jadi 2000000. Tetapi karena situasi race condition ini, hasilnya gak sampe 2000000 dan gak konsisten pula, kadang 1438727, kadang 1636524.

Kalau seperti ini, hasilnya gak sesuai dengan yang diinginkan. Lalu gimana solusinya?

Agar terhindar dari race condition, solusi yang populer adalah dengan melakukan locking. Jadi setiap proses yang berjalan, akan kita kunci sehingga proses lain harus menunggu. Jadi semuanya akan berjalan berurutan. Seperti ini kodenya.

var money int = 0
var lock sync.Mutex

func routine() {
    for i := 0; i < 1000000; i++ {
        money++
    }
}

func main() {
    wg := sync.WaitGroup{}
    wg.Add(2)
    go func() {
        defer wg.Done()
        lock.Lock()
        routine()
        lock.Unlock()
    }()
    go func() {
        defer wg.Done()
        lock.Lock()
        routine()
        lock.Unlock()
    }()
    wg.Wait()

    fmt.Println(money)
}

Di situ kita kunci saat menjalankan fungsi routine, sehingga saat ada proses lain yang akan masuk, wajib menunggu kuncian terbuka dahulu. Intinya, walaupun keduanya berjalan secara konkuren, tetapi saat mengakses data yang sama, proses dipaksa saling menunggu.

Penutup

Jadi, itulah bahayanya race condition. Pengen aplikasi ngebut dengan memanfaatkan concurrency atau multithreading, ehhh jangan lupa juga untuk singkronisasinya ya, supaya gak kena race condition.

Terima kasih sudah baca.

Kalau mau diskusi, komen aja. Kalau mau berteman, bilang aja ๐Ÿ˜Ž