Golang Technical Essay (ii) Understanding Goroutine

Source: Internet
Author: User

Processes, threads, and co-routines

To understand what Goroutine is, let's take a look at the differences between processes, threads, and the process, which can help us understand goroutine better.

Process : Allocate a complete and independent address space, have its own independent heap and stack, neither share the heap, nor share the stack, the process of switching occurs only in the kernel state, by the operating system scheduling.
Threads: And other threads of this process share the address space, have their own separate stacks and shared heaps, share heaps, do not share stacks, and switch threads are generally scheduled by the operating system (standard threads Yes).
co-process : Similar to threads, shared heaps, non-shared stacks, the switch of the co-process is typically controlled explicitly by the programmer in Code.

The switching of processes and threads depends primarily on the control of the time slices (about how processes and threads are dispatched, see this article: http://blog.chinaunix.net/ uid-20476365-id-1942505.html), and the transition of the co-process is mainly dependent on itself, the benefit is to avoid meaningless scheduling, which can improve performance, but also therefore, the programmer must bear the responsibility of scheduling.

Goroutine can be regarded as the implementation of the go language of the association, from the Baidu encyclopedia to see the definition of the association: As with subroutines, the Association (coroutine) is also a program component. The process is more general and flexible relative to subroutines, but in practice it is as broad as no subroutines. In fact, we can treat the routine as a special case of the association process. In general, if you do not explicitly give up the CPU, you will always execute the current process.

Brief analysis of Goroutine

We know that Goroutine is the go language implementation of the association, it is natively supported by the language, compared to the general way of implementation of the library, Goroutine more powerful, its scheduling is to a certain extent by the Go Runtime (runtime) management. One of the benefits is that when a goroutine is blocked (such as a synchronous IO operation), the CPU is automatically assigned to the other goroutine.

The use of Goroutine is very simple, for example Foo is a function:

go foo()

Just a keyword go is done, here will start a goroutine execute Foo function, and then the CPU continues to execute the following code. Although Goroutine is started here, it does not mean that it will be dispatched immediately, and the dispatch of the Goroutine is discussed later.

Goroutine is very lightweight, it is a piece of code, a function entry, and a stack allocated on the heap (the initial size is 4K, will be deleted as the execution of the program grows automatically). So it's very cheap and we can easily create tens of thousands of goroutine.

Go run-time scheduling

By default, all Goroutine will run in a native thread, i.e. only one CPU core is used. In the same native thread, if the current goroutine does not block, it will not give up CPU time to other goroutines of the same thread. In addition to the thread that is blocked by the system call, the Go runtime will start a maximum of $GOMAXPROCS threads to run Goroutine.

So how is goroutine being dispatched? We start with the Go program launch. The GO program will first create a special kernel thread Sysmon, from the name can be seen that its responsibility is responsible for monitoring, goroutine behind the dispatch can be said to be done by it.

Next, we look at its scheduling model, the current implementation of the go language is n:m. That is, a certain number of user threads are mapped to a certain number of OS threads, where the user thread in Go is the goroutine. The go language scheduling model needs to figure out three concepts: M, p, and G, as indicated:

m represents the OS thread, and G represents the Goroutine,p concept, which represents the execution context, the number of which is determined by the $GOMAXPROCS , in general, exactly equal to the number of processors. M must bind with P to execute G, and the scheduler needs to ensure that all p has g execution to ensure parallelism. Such as:

As we can see, there are currently two P, each bound to a m, and executed a goroutine, we can also see that each p also hangs a G queue, this queue is a private task queue, they are actually runnable state goroutine. When using the GO Keyword declaration, a goroutine is added to the tail of the run queue. Once a goroutine runs to a dispatch point, the context takes a goroutine out of the run queue, sets the stack and instruction pointers, and starts running the new goroutine.

So what are the scheduling points for switching goroutine in go? There are three specific cases:

    • Call the runtime gosched function. Goroutine actively abandons the CPU, the Goroutine is set to the runnable state, which is then placed in a global wait queue, and P continues to execute the next goroutine. Using the runtime gosched function is an active behavior, typically called when the CEO is in the task and wants other goroutine to be executed.
    • Call the runtime Park function. Goroutine enters the waitting state, unless the runtime ready function is called on it, the goroutine will never be executed. and P will continue to execute the next goroutine. The use of the runtime Park function is typically called when a condition cannot continue to run if it is not satisfied, and needs to be runtime ready to wake it up if the condition is met (it remains to be seen if the global wait queue is joined after Wake-up). Like channel operations, timers, network poll, etc. are possible park goroutine.
    • Slow system calls. Such a system call would block the wait, and in order for the other G hanging on the p to be executed, the goroutine would need to be transferred to another OS thread. This is done by first setting the p to the Syscall state and then the thread entering the system call blocking wait. The previously mentioned SYSMOM thread scans all p periodically and discovers that a P is in the Syscall state, separating m from P (effectively separating m from P only if the Syscall execution time exceeds a certain threshold). The runtime assigns another m and this p binding, which continues to execute the other G in the queue. When the previously blocked M is returned from the system call, it puts the goroutine into the global wait queue and then goes to sleep.

      The diagram depicts the separation process of M and p.

The dispatch point is clear, but the whole model is incomplete. We know that when using go to invoke a function, a new goroutine is generated into the queue of the current p, so when will the other OS threads be generated, and how does each OS thread load-balance?

When M gets an executable g from the queue, it first checks if there is a waiting g in its own queue, if there is a waiting g, and there is also free p, then the runtime is assigned a new m (if there is an OS thread in the sleep, it is awakened directly, If not, a new OS thread is generated) to share the task.

If an M discovery queue is empty, it is processed by taking a G from the global queue first. If the global queue is also empty, it will randomly intercept half of the queue from another P (stealing task), and if all p is found to have no g to steal, the M will fall asleep.

The whole scheduling model is basically like this, and all the scheduling of the same, in response time, this cooperative scheduling is flawed. It is easy to cause a process to not be executed for a long time. But overall, the benefits are even more impressive. Want to know more can look at some of the resources I listed below, or directly look at its source: http://golang.org/src/runtime/proc.c

Master Portal: Golang Technical essay

Resources
    1. Co-process
    2. System knowledge Behind the Goroutine
    3. The Go Scheduler
    4. Goroutine and Scheduler

Golang Technical Essay (ii) Understanding Goroutine

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.