Konkurensi

Konkurensi adalah komposisi / struktur dari berbagai proses yang berjalan secara bersamaan. Fitur untuk melakukan konkurensi dalam golang adalah Go Routine.

Go Routine

  • Sebuah thread yang ringan, hanya dibutuhkan 2kB memori untuk menjalankan sebuah go routine

  • Aksi go routine bersifat asynchronous, jadi tidak saling menunggu dengan go routine yang lain.

  • Proses yang hendak dieksekusi sebagai go routine harus berupa fungsi tanpa return yang dipanggil dengan kata kunci go

package main

import "time"

func Salam(s string) {
    for i := 0; i <= 10; i++ {
    println(s)
    time.Sleep(1000 * time.Millisecond)
    }
}

func main() {
    // salam tidak pernah tercetak karena dijalankan secara konkuren. 
    // Sehingga tidak akan ditunggu oleh func main, dan langsung exit.  
    go Salam("Selamat Pagi")
}
  • Go routine jalan di multi core processor, dan bisa diset mau jalan di berapa core.

Channel

  • Untuk mengsinkronkan satu go routine dengan go routine lainnya, diperlukan channel

  • Channel digunakan untuk menerima dan mengirim data antar go routine.

  • Channel bersifat blocking / synchronous. Pengiriman dan penerimaan ditahan sampai sisi yang lain siap.

  • Channel harus dibuat sebelum digunakan, dengan kombinasi kata kunci make dan chan

  • Aliran untuk menerima / mengirim data ditunjukkan dengan arah panah

Channel dengan buffer

  • Panjang buffer ditambahkan pada fungsi make sebagai argumen kedua

  • Buffering menyebabkan pengiriman dan penerimaan data berlangsung secara asynchronous

  • Pengiriman ke kanal buffer akan ditahan bila buffer telah penuh. Penerimaan akan ditahan saat buffer kosong.

  • Jika pengiriman data melebihi panjang buffer, maka akan diperlakukan secara synchronous.

Range dan Close

  • Range merupakan perulangan dari sebuah channel

  • Pengirim bisa menutup sebuah channel untuk menandai sudah tidak ada data yang dikirim lagi.

  • Penutupan ini hanya optional. Artinya pengirim boleh melakukan close maupun tidak.

  • Yang melakukan close hanya pengirim. Karena jika yang melakukan close adalah penerima, dan ada routine yang melakukan pengrimana akan menyebabkan panic.

  • Penerima bisa menambahkan pengecekan, jika masih ada data yang dikirim maka akan diterima.

Select

  • Channel diperlukan untuk pertukaran data antar go routine

  • Jika melibatkan lebih dari satu go routine, diperlukan fungsi kontrol melalui select

  • Select akan menerima secara acak mana data yang terlebih dahulu tersedia

Select Default

  • Jika saat select tidak ada channel yang siap diterima maka akan dijalankan baris kode default

Select Timeout

  • Teknik tambahan untuk mengakhiri select jika tidak ada penerimaan data

Hati-hati jika ingin menggabungkan antara select timeout dengan default, karena bisa terjadi looping forever.

Ini disebabkan time.After(time.Second * 5) selalu dibuat setiap looping seleksi, untuk mengatasinya, buat variable untuk menampung timeout agar timeout dikenali disetiap looping.

Sync Mutex

  • Channel dipakai untuk komunikasi antar go routine

  • Jika tidak ingin berkomunikasi karena ngin memastikan hanya satu goroutine yang dapat mengakses suatu variabel pada satu waktu untuk menghindari konflik, digunakan sync mutex

  • mutex adalah mutual exclusion dengan fungsi Lock dan Unlock

Sync.WaitGroup

  • Kadang kita perlu menjalankan satu group routine yang terdiri dari beberapa go routine.

  • Kita ingin mengontrol group rutin tersebut dengan melakukan sinkronisasi (synchronous).

  • Fitur sync.WaitGroup memungkinkan kita untuk menunggu semua group routine selesai.

  • Untuk mencegah suatu routine berlangsung lama dibanding routine lainnya, dipasang context dengan deadline.

  • Jika ada satu error di salah satu routine, maka seluruh routine yang sedang jalan akan dicancel.

Group Routine

  • Jika dijalankan kemungkinan tidak ada hasil yang diprint, atau mungkin cuma ada 1x print.

  • Tidak ada garansi apakah suatu routine bisa selesai dieksekusi.

  • Go menjalankan fungsi main, dan ketika fungsi main berakhir, maka berakhir juga seluruh program.

  • Kode di atas menjalankan sekelompok goroutine dan kemudian keluar sebelum mereka punya waktu untuk eksekusi.

Wait Group

  • Solusi untuk kasus di atas adalah dengan menggunakan standar library sync.WaitGroup

  • wg.Add() untuk counter berapa goroutine yang sudah ditambahkan. Setiap kali hendak menjalankan gouroutine, tambahkan counter dengan perintah wg,Add(1).

  • wg.Done() untuk menandai suatu routine sudah selesai

  • wg.Wait() untuk menunggu seluruh counter routine sudah nol (semua goroutine telah selesai).

  • Perhatikan saya mengenalkan variabel local id sebagai id sebuah goroutine. Ini adalah mekanisme aman menggunakan variabel local. Karena jika menggunakan varibel luar i, akan terjadi konflik karena menjalankan potensi race condition.

  • Di bawah ini adalah contoh kode yang salah karena tidak menggunakan variabel local.

Handling Error

  • Kode di atas sederhana dan optimis tidak terjadi error, padahal aplikasi riil pasti ada penanganan error.

  • Library golang.org/x/sync/errgroup digunakan untuk handling error.

  • Ingat untuk menggunakan variabel local sebagai id

  • Error yang ditangkap adalah error pertama yang dihasilkan oleh routine.

Context

  • context berguna untuk menjaga agar context dari client bisa diiikuti.

  • context bisa digunakan untuk menyimpan variabel yang siklus hiduonya sesuai context.

  • context bisa digunakan untuk melakukan deadline maupun cancell ation suatu fungsi.

  • context bisa digunakan untuk melakukan cancellation kode saat context sdh berakhir.

Kita bisa menambahkan deadline suatu context

Bandingkan jika kita tidak handle context, maka cancellation jadi tidak berfungsi.

Last updated

Was this helpful?