Lompat ke konten Lompat ke sidebar Lompat ke footer

Golang Concurrency #10

 Ya, ada perbedaan signifikan jika kita menempatkan wg.Wait() dan close(results) di goroutine terpisah. Mari kita bahas pro dan cons, serta mekanismenya.


1. Jika wg.Wait() dan close(results) Tetap di Goroutine Utama (Seperti Kode Awal)

Kode:

go func() { wg.Wait() close(results) }()

Mekanisme:

  • Worker tetap berjalan dan memproses job dari jobs.
  • Goroutine utama tidak akan menunggu worker selesai, karena wg.Wait() ada di goroutine terpisah.
  • Begitu semua worker selesai (wg.Done() dipanggil oleh masing-masing worker), wg.Wait() akan selesai dan menutup channel results.
  • Goroutine utama tetap bisa membaca dari results tanpa menunggu wg.Wait() selesai.

Pros:Lebih fleksibel: Bisa langsung mulai membaca hasil dari results sambil worker masih berjalan.
Potensi lebih responsif: Goroutine utama bisa membaca hasil lebih cepat tanpa harus menunggu semua job selesai.

Cons:Risiko race condition jika loop membaca results dijalankan sebelum worker selesai sepenuhnya.
Sulit dipahami jika tidak terbiasa dengan concurrency di Go.
Jika ada bug dan wg.Wait() tidak selesai, close(results) bisa jadi tidak pernah dipanggil, menyebabkan deadlock.


2. Jika wg.Wait() Tetap di Goroutine Utama (Seperti Kode Awal)

Dalam kode awal, kita tidak menaruh wg.Wait() di goroutine terpisah.

Kode Awal:

wg.Wait() close(results)

Mekanisme:

  • Goroutine utama akan menunggu (wg.Wait()) sampai semua worker selesai.
  • Setelah semua worker selesai, close(results) dipanggil.
  • Goroutine utama kemudian mulai membaca hasil dari results.

Pros:Lebih aman: Goroutine utama hanya membaca hasil setelah worker selesai, menghindari race condition.
Lebih mudah dipahami dan lebih deterministik.
Tidak ada risiko membaca dari channel results sebelum semua data selesai diproses.

Cons:Goroutine utama harus menunggu semua job selesai sebelum mulai membaca results.
Kurang optimal untuk kasus di mana kita ingin memproses hasil secara real-time.


3. Jika close(results) Ditaruh di Worker Terakhir

Alternatif lain adalah menutup results dari salah satu worker terakhir yang selesai.

Kode:

go func() { wg.Wait() close(results) }()

Mekanisme:

  • Setiap worker akan memproses job seperti biasa.
  • Begitu semua worker selesai (wg.Done() dipanggil di setiap worker), wg.Wait() selesai.
  • Setelah wg.Wait() selesai, close(results) dipanggil.

Pros:Lebih real-time: Bisa membaca results sambil worker masih berjalan.
Tidak memblokir goroutine utama untuk menunggu worker selesai.

Cons:Masih ada risiko jika ada worker yang mengalami deadlock atau tidak selesai.
Harus dipastikan bahwa close(results) hanya dipanggil sekali (karena menutup channel yang sudah tertutup akan panic).


Kesimpulan:

  1. Jika ingin membaca hasil setelah semua worker selesai
    → Gunakan wg.Wait() di goroutine utama, lalu close(results).
    Stabil, aman, tidak ada race condition.

  2. Jika ingin membaca hasil seiring dengan pemrosesan worker
    → Bisa gunakan goroutine terpisah untuk wg.Wait() dan close(results).
    Lebih kompleks, harus hati-hati dengan race condition.

  3. Jika ingin lebih fleksibel tanpa blocking goroutine utama
    → Bisa mempertimbangkan pola lain seperti menggunakan buffer besar di results agar pembacaan bisa dilakukan lebih bebas.

💡 Pilihan terbaik tergantung pada use case dan trade-off antara performa vs determinisme.