


Understanding golang blocking channel behavior by writing multiple times to the channel
In this article, editor Youzi will introduce to you how to understand the behavior of golang blocking the channel by writing multiple times to the channel. In golang, channels are an important mechanism for passing data between coroutines. When a channel is full, write operations are blocked until the channel becomes free. We'll demonstrate this behavior with a simple example and explain how blocking channels work and how to use them. Whether you are a beginner or an experienced golang developer, you can gain useful knowledge and practical experience from this article. let's start!
Question content
I am new to golang and trying to understand concurrency in the language. I have a code that pushes some values to a channel and then reads them.
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") }
The output of the above program is
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
I can't understand why 4.
(another write to channel) is executed before 5.
(first read from channel) because 3.
will block and the channel will be unavailable until the value is read from it (in step 5.
). Did I misunderstand the blocking behavior, in step 3.
there is only the main
goroutine block and Greet
(in step 4.
) Can additional values be written to a channel? An explanation would really clear up my confusion :)
cheers, D.D.
<小时/>Thanks for your reply, I've created a simpler program to demonstrate. concurrent
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) }
The deadlock
can be fixed by exchanging the c <- 1
and go do2(c)
statements.
Workaround
In Go, when you send a value on a channel (c <- "main::Hello"
in step 3), send The Goroutine will block until another Goroutine is ready to receive a value from the channel. However, this does not mean that no other goroutines can continue executing. In your code, both the Greet
and Greet2
coroutines are waiting for the value from the channel, so when you send the value in step 3, one of them (no guarantee which one) ) will unblock and continue execution.
Let me break down the sequence of events step by step:
- The main program starts and you create a channel
c
. - You declare two goroutines,
Greet
andGreet2
, and both are waiting for a value from the channel. - You send a value "main::Hello" on the channel, which blocks the main goroutine until other goroutines read data from the channel. However, one of the two Goroutines (
Greet
orGreet2
) is not blocked from receiving the value. -
Greet
Unblock and continue execution. It logs the message "4. Add 'Greet::John' to channel..." and sends "Greet::John!" on the channel. This blocksGreet
again because no other goroutine can read from the channel at this time. -
Greet2
Unblock and continue execution. It logs the message "5. Read Greet2::main::Hello" and reads the value "main::Hello" from the channel. - Main unlocks, records "6. Read main::Greet::John!" and reads "Greetings::John!" from the channel.
- Main sends another value "main::Bye" on the channel. At this point,
Greet
is still blocked while writing to the channel, andGreet2
is blocked from not reading from the channel. - Since
Greet
is still blocked on write, it never logs "8. Read Greet::main::Bye !" - Main site.
So the key to understanding the behavior here is that when you send a value on a channel, it unlocks any goroutines that are waiting to read data from the channel. The order in which waiting goroutines are unblocked is undefined and depends on the scheduler. In your case, Greet2
happens to be unlocked first, but it could also be Greet
.
In summary, the behavior you observe is entirely consistent with how Go channels work, with the caveat that execution order among competing Goroutines is not guaranteed.
The above is the detailed content of Understanding golang blocking channel behavior by writing multiple times to the channel. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

Use Golang to develop powerful desktop applications. With the continuous development of the Internet, people have become inseparable from various types of desktop applications. For developers, it is crucial to use efficient programming languages to develop powerful desktop applications. This article will introduce how to use Golang (Go language) to develop powerful desktop applications and provide some specific code examples. Golang is an open source programming language developed by Google. It has the characteristics of simplicity, efficiency, strong concurrency, etc., and is very suitable for

Security challenges in Golang development: How to avoid being exploited for virus creation? With the wide application of Golang in the field of programming, more and more developers choose to use Golang to develop various types of applications. However, like other programming languages, there are security challenges in Golang development. In particular, Golang's power and flexibility also make it a potential virus creation tool. This article will delve into security issues in Golang development and provide some methods to avoid G

Title: Steps and techniques for using Golang programming on Mac In the current field of software development, Golang (also known as Go), as an efficient, concise, and highly concurrency programming language, has attracted the attention of more and more developers. use. When programming Golang on the Mac platform, you can use some tools and techniques to improve development efficiency. This article will introduce the steps and techniques of using Golang programming on Mac, and provide specific code examples to help readers better understand and apply. Step 1: Install Gol

Golang (Go language for short) as a programming language has gradually emerged in the blockchain field in recent years. Its efficient concurrent processing capabilities and concise syntax features make it a favored choice in blockchain development. This article will explore how Golang helps the development of blockchain and demonstrate its superiority in blockchain applications through specific code examples. 1. Golang’s advantages in the blockchain field: Efficient concurrent processing capabilities: Nodes in the blockchain system need to process a large amount of transactions and data at the same time, and Gola

Golang is an open source programming language developed by Google and is widely used in back-end service development, cloud computing, network programming and other fields. As a statically typed language, Golang has an efficient concurrency model and a powerful standard library, so it is favored by developers. However, in actual development, Golang developers usually need to combine other programming languages for project development to meet the needs of different scenarios. PythonPython is an object-oriented programming language that is concise, clear, and easy to learn.

Gokit is a Golang microservice framework that improves API performance through optimized, scalable, maintainable and test-friendly features. It provides a range of tools and patterns that enable users to quickly build performant and maintainable APIs. In actual production, it is widely used in API construction of large platforms such as Netflix, Spotify and Uber, handling massive requests.

As a fast and efficient programming language, Golang language is favored by more and more developers. However, in daily development, we will inevitably encounter various errors. How to correctly analyze the causes of errors and find solution strategies is an important skill that every Golang developer needs to understand and master in depth. Error analysis type assertion failure In Golang, type assertion is a common operation, but sometimes if the types do not match, panic will occur. Here is a simple example: varxinter

Title: Sharing practical techniques for replacing spaces in Golang. With the popularity and development of the Internet, program design and development have become more and more important. In the programming process, data processing is a very critical part. When processing text data, you often encounter situations where you need to replace spaces. This article will share how to implement the technology of replacing spaces in Golang and provide specific code examples. Why do I need to replace spaces? Spaces are one of the common special characters in text data. Sometimes we need to replace spaces with other characters or remove spaces.
