An introduction to
In the Go official website, the Channel type is defined as follows.
A channel provides A mechanism for [concurrently executing functions provides] (golang. Google. Cn/ref/spec # Go…). to communicate by sending and receiving values of a specified element type. The value of an uninitialized channel is nil.
Channels provide a mechanism for concurrent execution of functions that communicate by sending and receiving values of specified element types. The value of an uninitialized channel is nil.
“Do not communicate by sharing memory, but share memory by communicating.” This sentence reflects the concept of Go language for concurrent design, and Channel is also an important member of the realization of CSP theory.
Basic operation
Now let’s talk about Channel.
For me, there are two kinds of channels:
- Unbuffered: Unbuffered in concurrent programming, as in synchronization.
- Caching: Caching is asynchronous.
The creation of unbuffered channels is similar, but the parameters are different
Talk is cheap, Show Me the Code — Linux founder Linus
Let’s use a simple code to describe the creation and operation of a channel.
Ch1 := make(chan int) // Ch2 := make(chan int, 1) ch2 < -1 ch2 := make(chan int, 1) ch2 < -1Copy the code
We create channels above, including int to specify the type of channel that can be put as.
To understand a channel, we can first think of it as a FIFO queue.
We can think of CH2 as a queue where we can put one element.
What about CH1? Is it a channel that can hold zero elements? Yes, that’s right! So how do you communicate between coroutines via CH1?
Remember we said at the top that there are two kinds of channels, one of which is synchronous? In other words, in order for two coroutines to communicate via CH1, they have to shake hands. When a coroutine puts data into CH1, it must block and wait for another ctrip to pick it up.
The flow of coroutines reading and writing to channels:
- If the sender writes data to the buffer, the waiting receiver will wake up. Multiple recipients will try to read data from the buffer. If no data is read, the receiver will fall into sleep again.
- When the receiver reads data from the buffer, the sender will wake up. The sender will try to write data to the buffer. If the buffer is full, the sender will fall into sleep again.
Have encountered the pit
- closed
chan
You can’t write. You can read - for
channel
The best way to traverse is using range
The source code
The operation of Channel is relatively simple, let’s take a look at the internal implementation of the Go source code. The chan structure is defined in ${GOROOT}/ SRC /runtime/chan.go.
type hchan struct {
qcount uint // total data in the queue
dataqsiz uint // size of the circular queue
buf unsafe.Pointer // points to an array of dataqsiz elements
elemsize uint16
closed uint32
elemtype *_type // element type
sendx uint // send index
recvx uint // receive index
recvq waitq // list of recv waiters
sendq waitq // list of send waiters
// lock protects all fields in hchan, as well as several
// fields in sudogs blocked on this channel.
//
// Do not change another G's status while holding this lock
// (in particular, do not ready a G), as this can deadlock
// with stack shrinking.
lock mutex
}
Copy the code
qcount
– Number of elements in Channel;dataqsiz
– The length of the loop queue in a Channel;buf
– Buffer data pointer to Channel;sendx
– The location to which the sending operation of a Channel is processed;recvx
– The position to which the receive operation of a Channel is processed;
Using the structure above, we can abstract the following picture:
summary
Channel is a new member of concurrency control. Although it has internal locks, it is insensitive to us. In the official network library, Go uses many channels for concurrency control.
I’ll write it here and share it later.