preface

The two best things about Go are Goroutine and Chan. The typical application of the combination of the two CSP is basically a parallel development artifact recognized by everyone, which simplifies the development difficulty of parallel programs. Let’s take a look at CSP.

What is CSP

CSP, short for Communicating Sequential Process, is a kind of concurrent programming model. It is a powerful concurrent data model. It was proposed in the 1970s. A concurrency model that describes two independent concurrent entities communicating over a shared communication channel(pipe). In contrast to the Actor model, a channel in a CSP is a first class object that focuses not on the entity that sends the message, but on the channel that is used to send the message.

Strictly speaking, CSP is a formal language (similar to ℷ calculus) that describes interaction patterns in concurrent systems, and has thus become the theoretical source of a host of concurrent programming languages, leading to Occam/Limbo/Golang…

For programming languages such as Golang, only a small part of CSP is used, namely Process/Channel in theory (corresponding to goroutine/ Channel in language) : There is no dependency between these two concurrent primitives. Process can subscribe to any Channel, and a Channel does not care which Process is using it to communicate. Processes read and write around channels, forming a set of ordered blocking and predictable concurrency models.

Second, Golang CSP

Unlike the mainstream languages, which use shared memory to control concurrency, Go adopts CSP mode. This is a concurrency model used to describe two independent concurrent entities communicating over a shared communication Channel (pipe).

Golang uses some concepts of THE CSP model to realize concurrency for theoretical support. In fact, go language has not fully realized all theories of the CSP model, but only borrowed the two concepts of Process and channel. A Process is represented in the GO language as a Goroutine that is actually executed concurrently, with each entity sharing data through channel communication.

The CSP model of Go language is implemented by coroutine Goroutine and Channel:

  • Go coroutine Goroutine: A lightweight thread that is not an operating system thread, but uses an operating system thread in segments to achieve cooperative scheduling through the scheduler. A green thread, a tasklet, which differs from a Coroutine in that it can start a new tasklet when a block is found.

  • Channel: UNIx-like Pipe used for communication and synchronization between coroutines. Although coroutines are decoupled from each other, they are coupled to channels.

Third, the Channel

Goroutine and Channel are the two cornerstones of concurrent programming in Go. Goroutines are used to perform concurrent tasks, and channels are used for synchronization and communication between Goroutines.

Channel sets up a pipe between the gouroutine and transmits data in the pipe to realize communication between the gouroutine. Because it is thread-safe, it is very convenient to use; Channel also offers “first in, first out” features; It also affects blocking and awakening of goroutine.

I believe you must have seen a sentence:

Do not communicate by sharing memory; instead, share memory by communicating.

Don’t communicate by sharing memory. Communicate by sharing memory.

This is the concurrency philosophy of Go, which relies on the CSP model and is based on the Channel implementation.

The channel to realize CSP

Channel is a very important type in Go and is the first object in Go. Through channels, Go implements memory sharing through communication. Channels are an important means of passing data and synchronization between multiple Goroutines.

Using atomic functions and read/write locks can secure shared access to resources, but using channels is more elegant.

A channel literally means “channel”, similar to a pipe in Linux. The syntax for declaring channels is as follows:

Chan T // Declare a two-way channel chan< -t // declare a channel only for sending <-chan T // Declare a channel only for receiving COPYCopy the code

The declaration of a one-way channel, denoted by <-, indicates the direction of the channel. Once you understand that the code is written from left to right, you’ll immediately know what the direction of the channel is.

Because a channel is a reference type, its value is nil until it is initialized, which is done using the make function. We can pass it an int that represents the size of the channel buffer, and construct a buffered channel. A channel that does not pass or pass 0 constructs a non-buffered channel.

There are some differences: a non-buffered channel cannot buffer elements, and must operate in the order “send -> receive -> send -> receive ->…” If you want to send two elements in a row to a non-buffered CHAN and do not receive them, the first time will be blocked. For buffered channels, the operation should be “loose”. After all, it has the halo of “buffering”.

Both the send and receive operations on chan are converted to the underlying send and receive functions at compile time.

Channels are divided into two types: buffered and unbuffered. Operations on unbuffered channels can actually be considered “synchronous mode”, while buffered channels are called “asynchronous mode”.

In synchronous mode, the sender and receiver must be ready for synchronization, and data can be transferred between them only if they are both ready (essentially a memory copy, as you will see later). Otherwise, either party that performs a send or receive operation will be suspended, waiting for the other party to appear before waking up.

In asynchronous mode, both send and receive operations can proceed smoothly as long as the buffer slot is available (with spare capacity). Otherwise, the side of the operation (such as write) is also suspended until the opposite operation (such as receive) occurs.

To summarize: In synchronous mode, the operation succeeds only when the sender and receiver are paired; otherwise, the operation is blocked. In asynchronous mode, the operation succeeds only when the buffer slot has free capacity. Otherwise, the operation is blocked.

In simple terms, the CSP model consists of entities (threads or processes or coroutines) that execute concurrently and communicate with each other by sending messages, which in this case use channels, or channels.

The key to the CSP model is to focus on the channel, not the entity sending the message. Go language implements part of the CSP theory. Goroutine corresponds to the concurrent execution entity in CSP, and channel corresponds to the channel in CSP.

Four, Goroutine

Goroutine is the entity that actually executes concurrency. At the bottom, it uses coroutine to realize concurrency. Coroutine is a user thread that runs in user mode, similar to greenThread.

  • User space avoids the cost of switching between kernel and user mode
  • Scheduling can be done by the language and framework layers
  • The smaller stack space allows for the creation of a large number of instances

You can see that the second user space thread is not scheduled by the operating system. For example, greenThread in Java 1.3 is scheduled by the JVM (since Java has been changed to kernel thread), and Fiber in Ruby needs to be scheduled by itself. Goroutine is in golang level to provide a scheduler, and network IO library encapsulation, shielding complex details, external to provide unified syntax keyword support, simplify the cost of concurrent programming.

Goroutine scheduler

Go concurrent scheduling: G-P-M model

Go builds a unique two-level threading model on top of the kernel threads provided by the operating system. The Goroutine mechanism implements the M: N threading model. The Goroutine mechanism is an implementation of coroutine. Golang’s built-in scheduler can execute one coroutine per CPU in multi-core cpus.

Six, the last

Golang’s channels isolate Goroutine and allow concurrent programming to focus on channels. To some extent, this is similar to the decoupling of message queues. If you are interested, or take a look at the source channel, for a deeper understanding of the channel is very useful.

Go implements the CSP communication model through channels and is mainly used for messaging and event notification between Goroutines.

With Channel and Goroutine, concurrent programming for Go has become incredibly easy and secure, allowing programmers to focus on the business and achieve efficiencies.

Understand that technology is not the most important thing, it is just the tool to implement the business. An efficient development language lets you save time for more meaningful things like writing articles.

The above is about the Docker deployment Go project introduction, if you want to know more, please pay attention to “Go keyboard man” public number, exchange and learn together, ^_^!

Recommended articles:

Channel in Go