Pengenalan sync.Cond
sync.Cond
adalah proses locking yang digunakan dengan kondisi tertentu. sync.Cond
dalam paket sinkronisasi Golang mengimplementasikan variabel kondisional yang dapat digunakan dalam skenario dimana banyak reader
sedang menunggu sumber daya berbarengan. Cond pooling point: beberapa goroutine menunggu, 1 event notifikasi goroutine terjadi. Setiap Cond diasosiasikan dengan Lock
**(sync. Mutex atau sync.RWMutex) yang harus ditambahkan saat memodifikasi kondisi atau memanggil metode wait()
, untuk melindungi kondisi.
Kenapa kita harus menggunakan sync.Cond
?
Kondisi ini memang cocok kita gunakan untuk memerintahkan program agar yang berjalan pada goroutine untuk melakukan eksekusi itu dengan satu persatu. Jika ingin satu persatu seperti itu maka method signal()
dijalankan untuk mengaktifkan hanya satu goroutine saja. Sedangkan jika ingin mengaktifkan dan mengeksekusi program menggunakan semua goroutine maka bisa memakai method broadcast()
.
Penggunaan Method
NewCond()
digunakan membuat suatu kondisi dalam variabelBroadcast()
digunakan untuk memberi tahu semua goroutine agar tidka perlu menunggu lagiSignal()
digunakan untuk memberi tahu sebuah goroutine agar tidak perlu menunggu lagi
Implementasi dan sampel sync.Cond
Lihat pada program yang sudah dibuat dibawah ini.
var locker = &sync.Mutex{}
var cond = sync.NewCond(locker)
var group = &sync.WaitGroup{}
func WaitCondition(value int) {
cond.L.Lock()
fmt.Println("waiting ", value)
cond.Wait()
fmt.Println("Done ", value)
cond.L.Unlock()
group.Done()
}
Fungsi yang sudah kita buat ini adalah kondisi untuk mengeluarkan input dari waitCondition
dimana kita bisa mencetak value
yang dikirim ke dalam fungsi tersebut. Selanjutnya kita buat yang pertama dengan menggunakan method signal
. Berikut fungsi main
dibawah ini bagaimana menjalankan kondisi sync.Cond
ini.
func main() {
for i := 0; i < 10; i++ {
group.Add(1)
go WaitCondition(i)
}
go func() {
for i := 0; i < 10; i++ {
time.Sleep(1 * time.Second)
cond.Signal()
}
}()
group.Wait()
}
Jika kita menjalankan program ini, maka goroutine
yang sedang berjalan adalah sekitar 10, tetapi mereka masih menunggu kondisi bahwa signal
. Setelah kita panggil cond.Signal()
pada goroutine
selanjut-nya, maka input yang dikirim akan di cetak secara bertahap dengan jeda 1 detik karena kita melakukan set sleep
. Hasilnya pun tidak akan berurutan karena secara eksekusi akan berjalan secara berbarengan menggunakan goroutine
yang sedang aktif.
waiting 0
waiting 5
waiting 1
waiting 2
waiting 3
waiting 4
waiting 7
waiting 6
waiting 8
waiting 9
Done 0
Done 5
Done 1
Done 2
Done 3
Done 4
Done 7
Done 6
Done 8
Done 9
Lalu, bagaimana kalau kita ingin mengaktifkan semua goroutine
-nya berbarengan agar tidak perlu ada jeda 1 detik? Maka kalau kita ingin seperti itu kita perlu ubah yang awalnya memanggil cond.Signal()
menjadi cond.Broadcast()
. Method tersebut akan mengirim sinyal bahwa semua goroutine boleh aktif berjalan secara bersamaan. Berikut ini perintah untuk menjalankan semua goroutine
dibawah ini.
func main() {
for i := 0; i < 10; i++ {
group.Add(1)
go WaitCondition(i)
}
go func() {
for i := 0; i < 10; i++ {
time.Sleep(1 * time.Second)
cond.Broadcast()
}
}()
group.Wait()
}
Kesimpulan
sync.Cond
adalah operasi asynchronize
yang bisa kita gunakan untuk beberapa kondisi dimana misalkan kita ingin mengeksekusi data yang besar dengan beberapa kondisi agar goroutine
yang berjalan itu diseleksi tidak semuanya berjalan karena kita menunggu signal
mana goroutine yang lebih dahulu menjalankan perintahnya. Berbagai implementasi bisa kita gunakan agar lebih memudahkan proses menggunakan goroutine
menjadi lebih efektif.