This is the 25th day of my participation in Gwen Challenge

These reviews

If you don’t already know Go, I suggest you read mineGo from zero.

In this series of articles, I’ll take a closer look at the Go language and introduce advanced features such as package management, reflection, and concurrency.

The previous article introduced concepts related to the concurrency model of the Go language. Scheduling between threads is always a complex topic, but concurrent programming inevitably involves scheduling threads by the operating system. This article will detail common threading models.

Common threading model

According to the different access permissions of resources, the operating system will divide the memory into kernel space and user space. The instruction code of the kernel space has the ability to directly schedule the underlying resources of the computer, such as I/O resources. The user space code does not have the ability to access the underlying computing resources, so it needs to be switched to the kernel mode through system calls to apply for and schedule the underlying computing resources.

Threads, as the smallest unit the operating system can schedule, are also divided into user threads and kernel threads:

  • User threads are created, managed and destroyed by user-space code, and thread scheduling is done by user-space thread libraries (possibly programming language-level thread libraries), without switching kernel state, with low resource consumption and high efficiency. The competition for CPU is based on the dimension of the process. All user-level threads in the same process can only reuse the CPU time slice allocated by the process, so they cannot make good use of the advantages of CPU multi-core computing. When we talk about threads in general, we really mean user threads;
  • Kernel threads are managed and scheduled by the operating system and can directly operate the resources at the bottom of the computer. When threads are switched, the CPU needs to switch to the kernel state. It takes advantage of parallel computing on multi-core cpus, allowing developers to use kernel threads through system calls.

User-level threading model

In the user-level thread model, one process corresponds to one kernel thread, as shown in the figure below:

In-process multithreading management is done by user code, which makes thread creation, switching, and synchronization extremely lightweight and efficient, but this complex logic needs to be implemented in user code, generally depending on the programming language level. Simultaneous multithreading can not make good use of the advantages of CPU multi-core process and can only be executed by time-sharing multiplexing. When any process blocks, such as thread A’s REQUEST for I/O is blocked, it is likely to cause process-wide blocking, because the corresponding kernel thread of the process is deprived of CPU execution time because thread A’s I/O is blocked, and the entire process loses the right to execute code on the CPU.

Kernel-level threading model

In the kernel-level threading model, there is a kernel thread for each thread in the process, as shown in the figure below:

Every time a new thread is created in the process, the thread library of the operating system will be called. When a new kernel thread is created in the kernel, the operating system is responsible for the management and scheduling of the thread, which will result in the switch from the user state to the kernel state every time the thread switches the context, and there will be no small resource consumption. The number of threads created is also limited by the number of kernel threads created by the operating system kernel. The advantage is that multithreading can take full advantage of the CPU’s multi-core parallel computing power, because each thread can be independently assigned to the CPU by the operating system scheduling, and the blocking of one thread does not affect the execution of other threads in the process.

Two-level threading model

The two-level thread model is equivalent to the combination of user-level thread model and kernel-level thread model. One process will correspond to multiple kernel threads, and the scheduler in the process determines how the threads in the process correspond to the applied kernel threads, as shown in the figure:

The process allocates a certain number of kernel threads in advance, and then matches the threads it creates with the kernel process. Threads are called and managed by the in-process scheduler, while kernel threads are scheduled and managed by the operating system. This thread model not only can effectively reduce the resource consumption of thread creation and management, but also can provide the ability of thread parallel computing, but it brings great difficulty for developers to implement.

summary

This paper mainly introduces the common thread model of Go language, including user thread, kernel thread and two-level thread model. The user thread cannot be perceived by the operating system, and the process or kernel thread that the user thread belongs to can be directly scheduled by the operating system to allocate CPU usage time. Different threading models have been developed for this, with varying degrees of CPU usage among them.

Read the latest article, pay attention to the public number: AOHO Qiusuo