Rumah > Artikel > pembangunan bahagian belakang > Memahami penyegerakan.Cond in Go: Menyegerakkan Goroutine dalam Senario Pengeluar-Pengguna
Dalam pengaturcaraan serentak, penyegerakan adalah kunci untuk menghalang perlumbaan data dan memastikan urutan atau goroutin beroperasi dengan cara yang diselaraskan. Bayangkan anda menghadapi masalah untuk menyelaraskan berbilang pengeluar dan pengguna yang mengakses sumber yang dikongsi, seperti penimbal atau baris gilir. Cabaran serentak klasik ini dikenali sebagai masalah pengeluar-pengguna. Dalam senario ini, penyegerakan adalah penting untuk memastikan pengeluar tidak menulis ganti data dan pengguna tidak membaca data yang tidak sah atau basi. Penyegerakan adalah perlu, kerana tanpa penyegerakan yang betul, akses serentak kepada data yang dikongsi boleh menyebabkan keadaan perlumbaan, kerosakan data atau ranap sistem. Pengeluar perlu menunggu jika penimbal penuh, dan pengguna perlu menunggu jika penimbal kosong. Mungkin terdapat senario di mana anda mempunyai penimbal terhad dengan saiz tetap dan anda perlu mengurus akses kepadanya dalam kalangan berbilang pengeluar dan pengguna.
sync.Cond in Go ialah mekanisme isyarat yang membolehkan gorout menunggu sehingga syarat tertentu dipenuhi. Ia amat berguna untuk menyelaraskan aliran kerja yang kompleks di mana sesetengah gorout perlu menjeda pelaksanaan dan menunggu sehingga gorout lain menyelesaikan tindakan tertentu. Idea di sebalik penyegerakan.Cond agak ringkas dan mudah difahami:
Bayangkan anda mempunyai penampan (atau baris gilir) dengan saiz tetap. Berbilang pengeluar menjana item dan menambahkannya pada penimbal, manakala berbilang pengguna mengalih keluar item daripadanya. Cabarannya ialah:
Berikut ialah struktur kod awal:
package main import ( "fmt" "sync" "time" ) const bufferSize = 5 type Buffer struct { data []int mu sync.Mutex cond *sync.Cond } func (b *Buffer) produce(item int) { // Producer logic to add item to the buffer } func (b *Buffer) consume() int { // Consumer logic to remove item from the buffer return 0 } func main() { buffer := &Buffer{data: make([]int, 0, bufferSize)} buffer.cond = sync.NewCond(&buffer.mu) var wg sync.WaitGroup // Start producer goroutines for i := 1; i <= 3; i++ { wg.Add(1) go func(id int) { defer wg.Done() for j := 0; j < 5; j++ { // Each producer creates 5 items buffer.produce(id*10 + j) // Produce unique items based on id and j time.Sleep(100 * time.Millisecond) } }(i) } // Start consumer goroutines for i := 1; i <= 3; i++ { wg.Add(1) go func(id int) { defer wg.Done() for j := 0; j < 5; j++ { // Each consumer consumes 5 items item := buffer.consume() fmt.Printf("Consumer %d consumed item %d\n", id, item) time.Sleep(150 * time.Millisecond) } }(i) } wg.Wait() fmt.Println("All producers and consumers finished.") }
Tugas kami, sebagai seorang jurutera, adalah untuk melaksanakan kaedah pengeluaran dan penggunaan untuk mencapai keperluan ini. Kaedah menghasilkan menambahkan item pada penimbal dan memberitahu pengguna apabila item ditambahkan. Kaedah penggunaan mengalih keluar item daripada penimbal dan memberitahu pengeluar apabila item dialih keluar. Masalah ini boleh diselesaikan dengan lancar menggunakan penyegerakan.Cond untuk menunggu dan memberi isyarat apabila penimbal penuh atau kosong.
Berikut ialah pecahan cara sync.Cond digunakan dalam kaedah hasil dan penggunaan:
Permulaan:
buffer.cond = sync.NewCond(&buffer.mu)
Kaedah Pengeluar (menghasilkan):
func (b *Buffer) produce(item int) { b.mu.Lock() defer b.mu.Unlock() // Wait if the buffer is full for len(b.data) == bufferSize { b.cond.Wait() // Release lock and wait until signaled } // Add item to the buffer b.data = append(b.data, item) fmt.Printf("Produced item %d\n", item) // Signal a consumer that an item is available b.cond.Signal() }
Kaedah Pengguna (consume):
func (b *Buffer) consume() int { b.mu.Lock() defer b.mu.Unlock() // Wait if the buffer is empty for len(b.data) == 0 { b.cond.Wait() // Release lock and wait until signaled } // Remove item from the buffer item := b.data[0] b.data = b.data[1:] fmt.Printf("Consumed item %d\n", item) // Signal a producer that space is available b.cond.Signal() return item }
Dalam contoh ini:
Penyelarasan ini membolehkan pengeluar dan pengguna berkongsi penimbal tanpa gangguan atau kebuntuan, mengurus akses dengan cekap berdasarkan keadaan penimbal.
Bayangkan anda mempunyai tugas di mana berbilang goroutin perlu menunggu keadaan tertentu sebelum meneruskan, seperti:
Atas ialah kandungan terperinci Memahami penyegerakan.Cond in Go: Menyegerakkan Goroutine dalam Senario Pengeluar-Pengguna. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!