pemrograman

Mengenal Sync Cond Pada Golang

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 variabel
  • Broadcast() digunakan untuk memberi tahu semua goroutine agar tidka perlu menunggu lagi
  • Signal() 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.

comments powered by Disqus