Sebagai sebahagian daripada pakej rasmi Go, pakej penyegerakan mempunyai pernyataan berikut:
Pakej penyegerakan menyediakan primitif penyegerakan asas, seperti kunci mutex. Kecuali untuk jenis Once dan WaitGroup, kebanyakan jenis lain ditujukan untuk pustaka fungsi asas. Penyegerakan tahap yang lebih tinggi lebih baik dicapai melalui saluran dan komunikasi
Dalam kebanyakan contoh yang anda boleh temui membenarkan akses serentak, ramai yang menggunakan mutex untuk menyelesaikan masalah. Walau bagaimanapun, terdapat beberapa contoh yang menunjukkan cara menggunakan saluran untuk menyediakan mekanisme penyegerakan. Jadi, mari kita bincangkan dalam artikel ini.
Agar kunci mutex berfungsi, ia perlu dikunci apabila mengakses pembolehubah kongsi, dan ia perlu dibuka kunci selepas operasi selesai. Mutex yang sama tidak dibenarkan dikunci beberapa kali untuk mengelakkan keadaan perlumbaan.
Jika tiada penerima, penghantar akan menyekat, begitu juga jika tiada penghantar, penerima akan menyekat. Berdasarkan ciri ini, kita tidak boleh menggunakan saluran tidak buffer sebagai kunci.
Mari kita lihat sama ada saluran penimbal boleh digunakan sebagai kunci mutex.
Saluran bersaiz buffer 1 mempunyai ciri-ciri berikut: jika buffer penuh, penghantaran akan disekat jika penimbal dikosongkan , penghantaran akan disekat Nyahsekat.
Jelas sekali, ciri menyekat saluran ini adalah wajar Bandingkan dengan ciri mutex:
Apabila penimbal penuh<-->
Buffer dikosongkan<--> ciri melalui kod.
Kami menganggap bahawa terdapat lajur nama yang perlu ditulis pada fail, dan setiap nama perlu ditulis 1000 kali secara berterusan, dan tiada persimpangan nama yang berbeza dibenarkan.
package main import ( "errors" "fmt" "os" "sync" ) func main() { file, err := os.Create("record.txt") defer func() { if err := recover(); err != nil { fmt.Printf("Error encounter: %w", err) } file.Close() }() if err != nil { panic(errors.New("Cannot create/open file")) } ss := []string{ //string slice literals "James", "Avery", "Peter", "John", "Beau", } chanLock := make(chan int, 1) //1 var wg sync.WaitGroup for _, str := range ss { //2 wg.Add(1) //amended thanks to response from Wang //Sheng go func(aString string) { chanLock <- 1 //3 for i := 0; i < 1000; i++ { file.WriteString(aString + "\n") } <-chanLock //4 wg.Done() //5 }(str) //pass by value } wg.Wait() }
Dalam kod di atas, //1 kami mencipta saluran dengan penimbal 1. //2 Kami mencipta bilangan goroutin yang sama dengan bilangan nama. //3 bersamaan dengan mengunci, //4 bersamaan dengan membuka kunci, supaya berbilang goroutine boleh menulis nama pada fail record.txt secara serentak, tetapi hanya satu goroutine akan mengendalikan fail pada satu masa.
Perlu diingatkan bahawa kami menggunakan WaitGroup untuk memastikan goroutine utama tidak akan keluar sebelum goroutine kanak-kanak menyelesaikan tugas.
Semoga artikel ini membantu anda, nikmati pengekodan!
Atas ialah kandungan terperinci Belajar! Gunakan saluran buffer sebagai Mutexes. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!