Today, let’s take a look at what Golang did.
Golang, Golang, Golang really enough waves, today we take stock of the Golang concurrency those things, to be exact is goroutine, about multi-threaded concurrency, we temporarily put it away (mainly I still don’t know, dare not come out of the mess). Let’s not talk about the merits of Golang. Anyway is big guy in say, an just eat melon masses, occasionally dozen dozen soy sauce, escape ~.
Speaking of concurrency, and so on, a whole series of concepts came up, in order to make a self-care dish, and review it
Basic concept
process
Process definition
A process (English: process) is a program that is already running in a computer. Processes were once the basic operating unit of “ “` time-sharing systems. In process-oriented systems (such as early UNIX, Linux 2.4 and earlier), a process is the basic execution entity of a program; In thread-oriented systems (such as most modern operating systems, Linux 2.6 and later), the process itself is not the basic unit of operation, but the container for the thread.
The program itself is only a description of the instructions, the data, and their organization. It is a noun. The process is the actual operating instance of the program (those instructions and data). Several processes may be associated with the same program, and each process may run independently, either synchronously or asynchronously. Modern computer systems can load multiple programs into memory as processes at the same time, and use time sharing (or TDM) to give the impression of parallel running on a single processor. Similarly, operating systems or computer architectures that use multithreading (where each thread represents an independent execution context within a process), parallel threads of the same program can run at true time (on different cpus) on a multi-CPU host or network.
Process creation
The operating system needs a way to create processes.
The following four main events create processes
1. System initialization (simply understood as starting up after shutdown)
2. A running program executes a system call to create the process (for example, a friend sends a url and you click on it to open the browser and enter the page)
3. The user requests to create a new process (e.g., open a program, open QQ, wechat)
4. Initialization of a batch job
Termination of a process
After a process is created, it starts to run and process related tasks. But it doesn’t last forever. It’s done or gone. Process termination can occur in four ways
1. Normal withdrawal (voluntary)
2) Wrong exit (voluntary)
3. Crash exit (involuntary)
4) Killed by others (involuntarily)
Normal exit: You exit the browser, you click on it
Error exit: You are enjoying watching a TV show and suddenly a bug occurs in the program, causing you to exit
Crash Exit: Your program crashed
Killed by others: for example on Windows, use task manager to shut down the process
Process status
1. Running state (actual CPU usage)
2. Ready (running, but suspended while other processes are running)
3. Blocked (the process cannot run unless at some external time)
The first two states are logically similar. Processes in either state can run, but in the second state no CPU has been allocated and can run once it has been allocated
The third state differs from the first two in that the process in this state cannot run, even if the CPU is idle.
If you are interested, you can learn more about process implementation and multi-process design model
The process of pool
The application of process pool technology consists of at least the following two parts:
Resource process
The admin process assigns work to a pre-created idle process.
Management process
The management process is responsible for creating the resource process, handing off the work to the idle resource process, and reclaiming the resource process that has finished its work.
Resource process with the concept of administrative process is easy to understand, how the effective management of the resource management process, the distribution of tasks to process of resources, recycling process of idle resources, to the effective management of the resource management process, then the management process and the process of resources must be need interaction, through the IPC, signals, semaphores, message queues, pipelines to interact.
Process pooling: It doesn’t actually exist in our operating system exactly, but IPC, signals, semaphores, message queues, pipes, etc. manage multiple processes to reduce the constant on/off operations. In order to achieve the reduction of unnecessary consumption of resources
thread
define
A thread (English: thread) is the smallest unit in which an operating system can schedule operations. In most cases, it is contained within a process and is the actual operational unit of the process. A thread is a single sequential flow of control in a process, and multiple threads can be concurrent in a process, each performing a different task in parallel. In Unix System V and SunOS, they are also referred to as Lightweight processes, but more commonly referred to as kernel threads, while user threads are referred to as threads.
Threads are the basic unit of independent scheduling and dispatch. Threads A kernel thread that can be scheduled for the operating system kernel
Multiple threads in the same process share all system resources in that process, such as virtual address space, file descriptors, signal processing, and so on. But multiple threads in the same process have their own call stack, their own register context, and their own thread-local storage.
A process can have many threads working on it, each performing a different task in parallel. If the process has a lot of work to do that requires a lot of threads and calls a lot of cores, the benefits of multithreaded programming on a multi-core or multi-CPU, or hyper-threading enabled CPU are obvious: increased program throughput. Think of it in terms of people working. Cores are like people. The more people you have, the more things you can do at the same time. In a single CPU single-core computer, the use of multithreading technology, can also be responsible for THE PROCESS of I/O processing, human-computer interaction and often blocked part and the part of intensive computing separated to execute, write special workhorse thread to perform intensive computing, although multitasking is not as good as multi-core, but because of the ability of multithreading, Thus, the execution efficiency of the program is improved.
The thread pool
Thread pool (English: Thread pool) : a thread usage pattern. Too many lines will bring scheduling overhead, which will affect cache locality and overall performance. A thread pool maintains multiple threads, waiting for the supervisor to assign tasks that can be executed concurrently. This avoids the cost of creating and destroying threads while working on short-duration tasks. Thread pools not only ensure full utilization of the kernel, but also prevent overscheduling. The number of threads available should depend on the number of concurrent processors available, processor cores, memory, network sockets, and so on. For example, the number of threads is usually the number of cpus +2, because too many threads cause additional thread switching overhead.
A common way to schedule tasks to execute threads is to use synchronous queues, called task queues. Threads in the pool wait for tasks in the queue and put the completed tasks into the completion queue.
Thread pool modes are generally divided into two types: HS/HA semi-synchronous/semi-asynchronous mode and L/F leader and follower mode.
· Semi-synchronous/semi-asynchronous mode, also known as producer/consumer mode, is a common implementation method and relatively simple. It is divided into three layers: synchronous layer, queue layer and asynchronous layer. The main thread of the synchronization layer processes the work and stores it to the work queue. The worker thread takes out the work from the work queue for processing. If the work queue is empty, the worker thread that cannot get the work enters the suspended state. Because there is data communication between threads, it is not suitable for large-volume data exchange.
· Leader-follower mode. Threads in the thread pool can be in one of three states: leader, follower, or worker processor. There is only one leader thread in the thread pool at any one time. When the event arrives, the leader thread takes care of message separation, selects one of the follower threads as the successor leader, and then sets itself to worker state to handle the event. After processing, the worker thread sets its state to follower. This pattern is complex to implement, but avoids exchanging task data between threads and improves CPU cache similarity. In ACE(Adaptive Communication Environment), the leader-follower mode is implemented.
The scalability of thread pools has a significant impact on performance.
- Creating too many threads wastes resources, and some threads are underused.
- Destroying too many threads will cause you to waste time creating them again later.
- Creating a thread too slowly results in long waits and poor performance.
- Destroying threads is too slow, starving other threads of resources.
coroutines
Coroutine, English called Coroutine, also known as micro thread, fiber, Coroutine is a user – mode lightweight thread.
Coroutines have their own register context and stack. When coroutine schedules a switch, the register context and stack are saved elsewhere, and when cut back, the previously saved register context and stack are restored. Thus, the coroutine can preserve the state of the last call, that is, a specific combination of all local states, and each procedure reentry is equivalent to entering the state of the last call.
Coroutines are essentially single processes. Compared with multiple processes, coroutines do not need the overhead of thread context switch, atomic operation locking and synchronization, and the programming model is very simple.
serial
Multiple tasks, execute another task after completion.
Take a walk after eating (sit down to eat first, go for a walk after eating)
parallel
Multiple tasks and alternate execution
For example: cooking, a water wash vegetables, a absorption (dishes are dirty, wash the dish to write hands, jiao ~)
concurrent
Set out together
Eat while watching TV
Blocking and non-blocking
blocking
A blocked state is the state in which a program is suspended if it does not get the computing resources it needs. A program is said to block on an operation while it waits for it to complete and cannot continue to do anything else on its own.
Common blocking modes include network I/O, disk I/O, and user input blocking. Blocking is everywhere, including when the CPU switches context, and all processes can’t really process something, they can also block. If it is a multi-core CPU, the core that is performing a context switch operation is not available.
non-blocking
A program is said to be nonblocking if it does not block while waiting for an operation and can continue processing other things.
Non-blocking does not exist at any program level and under any circumstances. A program can be nonblocking only if the level of encapsulation includes individual subroutine units.
Non-blocking exists because blocking exists, and it is because of the time and inefficiency of a blocking operation that we make it non-blocking.
Synchronous and asynchronous
synchronous
In order to complete a certain task, different program units need some communication mode to coordinate in the process of execution. We call these program units synchronous execution.
For example, in the shopping system, it is necessary to use “line lock” as a communication signal to force different update requests to be executed in queue order, so that the operation of updating inventory is synchronous.
In short, synchronization means order.
asynchronous
In order to accomplish a task, different program units can accomplish the task without communication and coordination, and unrelated program units can be asynchronous.
For example, a crawler downloads a web page. After the scheduler calls the downloader, it can schedule other tasks without having to communicate with the downloader to coordinate behavior. Downloading, saving and other operations of different web pages are irrelevant, and there is no need to notify each other and coordinate. The completion time of these asynchronous operations is uncertain.
Asynchronous and non-asynchronous
After all that, processes, threads, and so on, it’s really uncomfortable. But I believe you have a preliminary probability, so here we will go into more depth to understand asynchronous and non-asynchronous.
Before we do that, let’s conclude that the evolution of all of these routes, in fact, acceleration is nothing more than a word, improve efficiency. (Crap ~)
There are two main factors to improve efficiency: increasing input in order to increase output and avoiding unnecessary wastage as much as possible (e.g., reducing context switches, etc.).
The difference between asynchronous code and non-asynchronous code is simply whether it can do things on its own that we don’t need to do.
We think backwards from the results,
For example, we send a network request and have network I/O blocking in between, so we suspend it and move on to something else, and when it responds, we move on to the next step in this phase. So this is asynchronous
In addition: homework and go to the bathroom, I am writing homework at this time, suddenly, I want to go to the bathroom, go. I go to the bathroom and then I come back and do my homework, and I’m not making any progress while I’m in the bathroom, so we can think of it as non-asynchronous
goroutine
Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah.
How to do this is to define many tasks and let the system help us to assign these tasks to the CPU for concurrent execution.
One such mechanism is the Goroutine in the Go language. The concept of a Goroutine is similar to a thread, but the Goroutine is scheduled and managed by the Go runtime. The Go program intelligently allocates the tasks in Goroutine to each CPU. Go is considered a modern programming language because it already has scheduling and context switching mechanisms built in at the language level.
You don’t need to write your own processes, threads, and coroutines in Go programming. You only have one skill in your package — Goroutine. When you need to execute a task concurrently, you just wrap that task into a function and start a Goroutine to execute that function
Goroutine with thread
Growable stack
OS threads (operating system threads) typically have a fixed stack memory (usually 2MB). A Goroutine’s stack begins its life with a very small stack (typically 2KB). Goroutine’s stack is not fixed, it can be enlarged and shrunk as needed. Goroutine’s stack size can be limited to 1GB, although this size is rarely used. So it’s ok to create around 100,000 Goroutines at a time in Go.
Goroutine model
GPM is the implementation of Go language runtime level and a scheduling system implemented by Go language itself. Different from operating system scheduling OS threads.
· G is very easy to understand, it is a Goroutine, in addition to storing the information of the goroutine and the binding of the P.
· P manages a set of Goroutine queues. P stores the context (function pointer, stack address and address boundary) in which goroutine is currently running. P will perform some scheduling on its own goroutine queue (such as suspending the goroutine that occupies a long CPU time, running the subsequent goroutine, etc.). When its own queue is consumed, IT will fetch from the global queue. If the global queue is also consumed, it will grab tasks from other QUEUES of P.
· M ‘(‘ machine’) is the Go runtime virtual operating system kernel threads, M and kernel threads are generally one-to-one mapping relationship, a groutine is finally put on M execution;
P and M usually correspond one to one. Their relationship is: P manages a group of G mounted on M. When a G blocks on a M for a long time, the Runtime creates a new M, and the P where G blocks will mount other GS on the new M. Reclaim the old M when the old G is blocked or considered dead.
The number of P is set by runtime.GOMAXPROCS (maximum 256). After Go1.5, the default is the number of physical threads. Some P and M are added when concurrency is high, but not too much. Switching too often is not worth the cost.
In terms of thread scheduling alone, Go has an advantage over other languages in that OS threads are scheduled by the OS kernel, whereas Goroutine is scheduled by the Go runtime’s own scheduler, which uses a technique called M: N scheduling (multiplexing/scheduling m Goroutines to N OS threads). One big characteristic is goroutine scheduling is done under the user mode, does not involve frequent switching between kernel mode and user mode, including memory allocation and release, is at the user mode maintains a large memory pool, not directly call system malloc function (unless the memory pool needs to be changed), the cost is much lower than scheduling OS thread. On the other hand, it makes full use of multi-core hardware resources, approximately divides several Goroutines into physical threads, and the ultra-light weight of its own Goroutine ensures the performance of GO scheduling.
GOMAXPROCS
The Go runtime scheduler uses the GOMAXPROCS parameter to determine how many OS threads are needed to execute the Go code simultaneously. The default value is the number of CPU cores on the machine. For example, on an 8-core machine, the scheduler will schedule the Go code to eight OS threads simultaneously (GOMAXPROCS is n in m:n scheduling).
In Go, the runtime.gomaxprocs () function can be used to set the number of CPU cores that the current program occupies concurrently.
Prior to Go1.5, single core execution was used by default. After Go1.5, the total number of CPU logical cores is used by default.
The creation of a goroutine
Using a Goroutine is very simple. You can create a Goroutine for a function by preempting the function name with the go keyword.
A goroutine must correspond to a function, but it is possible to create multiple Goroutines to perform the same function.
Syntax is as follows
If you’re in the mood to give it a try right now, I just want to say, “Shaoxia, please wait.” I’m not done. I just showed you how to create a Goroutine, not how it works. Hee hee ~
First let’s look at the code without Goroutine, as shown in the following example
The input results are as follows
So let’s use Goroutine and run
Example code is as follows:
The output is as follows
At first glance, good guy speed is not an order of magnitude ah, ah ~
If you look closely, where are the 7’s and 9’s going? It’s gone, stare
The answer will be revealed in the next article
Looking forward to the next article, I’ll check out the second thing Golang does with concurrency. Goroutine’s concurrency control is handy
This article is from The huawei cloud community “One of those Things that Golang concurrency”, originally written by: PayneWu.
Click to follow, the first time to learn about Huawei cloud fresh technology ~