The following is a personal understanding, if wrong, please treatise
What
Goroutine is Golang in the Coroutine, also known as the process, Microsoft Dafa called fiber (Fiber).
The co-process is a finer-grained scheduling that can satisfy multiple threads of different processing logic to share a thread resource.
Why
Before talking about Goroutine, explain why you should use this technique:
It should be known that the most granular scheduling of the initial operating system is the kernel-level thread (thread), which is actually a stack plus a heap of resources. The operating system one will divide the CPU time slice to thread A, one will divide the CPU's time slice to thread B, rely on A and B's stack to save the execution state of A and B. At first, there were not many concurrent processing of the software, the thread pool was sufficient, but as the complexity of the software increased and the concurrency increased and the threads became scarce resources, go invented the goroutine and increased the utilization of threads in asynchronous processing.
How
Golang has a powerful scheduler maintenance Goroutine running on a kernel-level thread, ensuring that all goroutine are used and using CPU resources as equitably as possible. The main support for the entire scheduler is 4 important structures, M, G, P, Sched, respectively:
- m is a kernel-level thread, an M is a thread, Goroutine is running above M, and M is a large structure that maintains a lot of information such as the small Object memory cache (Mcache), the currently executing goroutine, the random number generator, and so on.
- p Full name is processor, the processor, its main purpose is to perform goroutine, so it also maintains a goroutine queue, which stores all the goroutine that need it to execute, the role of P can be a bit confusing , it was easy to start with the M conflict, and later to focus on their relationship.
- G is the goroutine implementation of the core structure, g maintenance of the goroutine required stack, program counter and its location m and other information.
- The Sched structure is the scheduler, which maintains queues with storage m and G, as well as some state information of the scheduler.
There is a graph on the network that describes the relationship between M, p, and g more accurately:
The hamster carried a pile of bricks to be processed in a car. M can be thought of as the hamster in the picture, p is the car, G is the brick in the car (the following description excerpt).
- Runqget, Gopher (M) trying to take out a brick (G) from his own car (P), of course, the result may fail, that is, the hamster's car is empty, no bricks.
- Findrunnable, if the hamster own car does not have bricks, that can not idle work is it, so the hamster will try to run to the factory warehouse to take a brick to deal with, the factory warehouse may not have bricks ah, this situation, the land rat did not lazy stop work, but quietly run out, Randomly stare at a small partner (gopher) and then try to steal half of the bricks from his car into his car. If many attempts to steal bricks have failed, it shows that there is no brick can be moved, this time the rat will return to the car park, and then sleep rest. If the hamster sleeps, the following process is of course stopped, and the hamster sleeps in the thread sleep.
- Wakep, to this process, the poor hamster found himself in the car there are many bricks ah, they can not handle it, and then look back at the parking lot there is idle car, immediately ran to the dorm, your sister, incredibly still have a small partner in sleep, directly to the bottom of a foot, "Your sister, incredibly still sleeping, Lao Tzu is almost exhausted, Get up and work and share the job. The little buddy woke up and took his car and went to work. Sometimes, poor hamster ran to the dorm but found no sleep in the small partner, so will be very disappointed, finally had to tell the factory owner-"Parking lot and idle car ah, I can not move, hurriedly from other factories to borrow a gopher to help it." Finally, the factory owner got a new hamster to work on.
- Execute, the hamster took the bricks into the fire and lit up happily.
Note: "Gopher steal brick" called Work stealing, a scheduling algorithm.
Here, it seems that the entire factory is functioning normally, impeccable appearance. No, there is a doubt unsolved, suppose the rat's car has a lot of bricks, it put a brick into the stove, when to take it out, put in the second brick? Do you want to keep the first piece of brick on fire before you take it out? It is estimated that the brick behind is really waiting for the flowers to be thanked. Here is to really solve the Goroutine scheduling, context switching problem.
Dispatch point:
When we look at the channel's implementation code, we can see that the runtime Park function is triggered when the channel reads and writes. After Goroutine calls Park, the Goroutine is set to the bit waiting state, discarding the CPU. The Goroutine of Park is in waiting state, and this goroutine is not in the car (P), and if it is not called runtime ready, it will never be executed again. In addition to channel operation, the timer, network poll, etc. may be park goroutine.
In addition to park can discard the CPU, calling the runtime gosched function can also let the current goroutine abandon the CPU, but unlike park, Gosched is to set Goroutine to Runnable State, Then put into the scheduler global waiting queue (that is, the factory warehouse mentioned above, this will understand why the factory warehouse will have bricks (G) it).
In addition, it is the turn of the system call, some system calls will also trigger the rescheduling. The go language is completely its own package system call, so in the encapsulation system call, can do a lot of hands and feet, that is, enter the system call when the execution of Entersyscall, exit and execute the Exitsyscall function. Only system calls that encapsulate the entersyscall can trigger a reschedule, which will change the state of the Trolley (P) to Syscall. Do you remember the Sysmon thread that was mentioned at the beginning? This system monitoring thread will scan all the cars (p), found a car (p) in the state of the Syscall, it is known that the car (p) encountered Goroutine is making a system call, so the system monitoring thread will create a new Gopher (M) To get this car in the Syscall to Rob, began to work, so that all the bricks in the car (G) can bypass the previous system call waiting. Was robbed of the car, such as the hamster system call back, found that his car did not, can not continue to work, so can only execute the system call Goroutine put back to the factory warehouse, his sleep went.
From the Goroutine dispatch point can be seen, the scheduler is still quite rough, scheduling granularity is a bit too big, fairness also did not think so good.
On-Site treatment:
Goroutine on the CPU swap out, constantly context switch, must be guaranteed to save the scene and restore the scene, save the scene is the Goroutine to abandon the CPU, the value of the relevant register to save to memory Recovery of the site is when the Goroutine regain the CPU, you need to put the previous register information from memory to the corresponding register. The
Goroutine, when actively discarding the CPU (park/gosched), involves invoking the runtime McAll function, which is also a compilation implementation, The Goroutine's stack address and program counter are saved to the Sched field of the G structure, and McAll is saved in the field. The function to restore the scene is Runtime Gogocall, which is called primarily in execute, which requires reloading the appropriate registers before executing the goroutine.