Rumah >pembangunan bahagian belakang >Golang >Memahami tingkah laku saluran menyekat golang dengan menulis beberapa kali ke saluran
Dalam artikel ini, editor PHP Youzi akan memperkenalkan kepada anda cara memahami tingkah laku golang menyekat saluran dengan menulis ke saluran berkali-kali. Dalam golang, saluran adalah mekanisme penting untuk menghantar data antara coroutine. Apabila saluran penuh, operasi tulis disekat sehingga saluran menjadi bebas. Kami akan menunjukkan tingkah laku ini dengan contoh mudah dan menerangkan cara menyekat saluran berfungsi dan cara menggunakannya. Sama ada anda seorang pemula atau pembangun golang yang berpengalaman, anda boleh memperoleh pengetahuan berguna dan pengalaman praktikal daripada artikel ini. Mari mulakan!
Saya baru mengenali golang dan cuba memahami konkurensi dalam bahasa. Saya mempunyai kod yang menolak beberapa nilai ke saluran dan kemudian membacanya.
package main import ( "log" "time" ) func Greet2(c chan string) { // logging to Stdout is not an atomic operation // so artificially, sleep for some time time.Sleep(2 * time.Second) // 5. until below line reads and unblock the channel log.Printf("5. Read Greet2:: %s\n\n", <-c) } func Greet(c chan string) { // 4. Push a new value to the channel, this will block // Process will look for other go routines to execute log.Printf("4. Add 'Greet::John' to the channel, block until it is read. Remember, 'Greet' goroutine will block and only other goroutines can run even though this go routine can pull the value out from the channel.\n\n") c <- "Greet::John!" // 8. This statement will never execute log.Printf("8. Read Greet:: %s !\n\n", <-c) } func main() { c := make(chan string) log.Println("1. Main start") // 2. Both go routine will be declared and both will // for a value to be inserted in the channel log.Println("2. Declare go routines.\n\n") go Greet(c) go Greet2(c) // 3. write will block log.Println("3. Add 'main::Hello' to the channel, block until it is read. Remember, 'main' goroutine will block and only other goroutines can run even though this go routine can pull the value out from the channel.\n\n") c <- "main::Hello" // Sleep to give time goroutines to execute time.Sleep(time.Second) // 6. read the channel value. log.Printf("6. Read main:: %s \n\n", <-c) // 7. Insert a new value to the channel log.Println("7. Add 'main::Bye' to the channel, block until it is read.\n") c <- "main::Bye" // Sleep to give time goroutines to execute time.Sleep(time.Second) log.Println("9. Main stop") }
Keluaran program di atas ialah
2023/09/02 21:58:07 1. Main start 2023/09/02 21:58:07 2. Declare go routines. 2023/09/02 21:58:07 3. Add 'main::Hello' to the channel, block until it is read. Remember, 'main' goroutine will block and only other goroutines can run even though this go routine can pull the value out from the channel. 2023/09/02 21:58:07 4. Add 'Greet::John' to the channel, block until it is read. Remember, 'Greet' goroutine will block and only other goroutines can run even though this go routine can pull the value out from the channel. 2023/09/02 21:58:10 5. Read Greet2:: main::Hello 2023/09/02 21:58:11 6. Read main:: Greet::John! 2023/09/02 21:58:11 7. Add 'main::Bye' to the channel, block until it is read. 2023/09/02 21:58:11 8. Read Greet:: main::Bye ! 2023/09/02 21:58:12 9. Main stop
Saya tidak faham kenapa 4.
(另一个写入通道)在 5.
(第一次从通道读取)之前执行,因为 3.
将阻塞,并且在读取值之前通道不可用来自它(在步骤 5.
中)。我是否误解了阻塞行为,在步骤 3.
中,只有 main
goroutine 块和 Greet
(在步骤 4.
) boleh menulis nilai tambahan pada saluran? Penjelasan benar-benar akan menjelaskan kekeliruan saya :)
Sekian, D.D.
Terima kasih atas balasan anda, saya telah mencipta program yang lebih mudah untuk ditunjukkan. Concurrency
package main import ( "fmt" ) func do2(c chan int) { fmt.Println(<-c) } func do(c chan int) { // 4. this statement is trying to write another value "2" to the channel // Channel already contains "1" as the value which has not been read yet. // this statement will wait for "1" to get read and block the execution. // Scheduler will look for other goroutines that can execute. // However, this("do") is blocked as well as "main" is blocked too and // there are no other goroutines to execute. // Hence, will result in a "Deadlock" fatal error. c <- 2 fmt.Println(<-c) } func main() { // 1. Declare a channel c := make(chan int) // 2. Declare "do" goroutine go do(c) // 3. write "1" to the channel // This will block and wait for program's other goroutines to read the value. // however, there is only "do" goroutine is defined can run at this point. // Scheduler, will try to run "do" goroutine. c <- 1 go do2(c) }
c <- 1
dan go do2(c)
. 死锁
可以通过交换c <- 1
和go do2(c)
语句来修复。
在 Go 中,当您在通道上发送值时(步骤 3 中的 c <- "main::Hello"
),发送 Goroutine 将阻塞,直到有另一个 Goroutine 准备好从通道接收值。然而,这并不意味着没有其他 goroutine 可以继续执行。在您的代码中, Greet
和 Greet2
c <- "utama::Hello"
dalam langkah 3), penghantaran Goroutine akan menyekat sehingga terdapat A Goroutine yang lain bersedia untuk menerima nilai daripada saluran. Walau bagaimanapun, ini tidak bermakna tiada gorout lain boleh terus dilaksanakan. Dalam kod anda, c
Izinkan saya memecahkan urutan peristiwa langkah demi langkah: Greet
和 Greet2
Program utama bermula dan anda mencipta saluran Greet
或 Greet2
Anda mengisytiharkan dua gorouti, Greet
解除阻塞并继续执行。它记录消息“4. 将‘Greet::John’添加到频道...”并发送“Greet::John!”在频道上。这会再次阻塞 Greet
Anda menghantar nilai "utama::Hello" pada saluran, yang menyekat goroutine utama sehingga goroutin lain membaca data daripada saluran. Walau bagaimanapun, salah satu daripada dua Goroutine (Greet2
Greet
在向通道写入时仍被阻止,而 Greet2
Greet
Main menghantar nilai lain "utama::Bye" pada saluran. Pada ketika ini, masih disekat pada penulisan, ia tidak pernah mencatatkan "8. Baca Salam:: utama::Selamat tinggal Greet2
碰巧首先被解锁,但也可能是 Greet
🎜Jadi kunci untuk memahami gelagat di sini ialah apabila anda menghantar nilai pada saluran, ia membuka kunci mana-mana goroutine yang sedang menunggu untuk membaca data daripada saluran tersebut. Susunan goroutin menunggu dinyahsekat tidak ditentukan dan bergantung pada penjadual. Dalam kes anda, 🎜 kebetulan dibuka kuncinya dahulu, tetapi mungkin juga 🎜. 🎜 🎜Ringkasnya, gelagat yang anda perhatikan adalah konsisten sepenuhnya dengan cara saluran Go berfungsi, dengan kaveat bahawa perintah pelaksanaan antara Goroutines yang bersaing tidak dijamin. 🎜
Atas ialah kandungan terperinci Memahami tingkah laku saluran menyekat golang dengan menulis beberapa kali ke saluran. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!