How to understand multithreading in JS

Basic knowledge

First, let’s review the knowledge of operating systems, namely:

  • Why do the concepts of processes and threads appear, and what problems do they appear to solve?
  • Concepts and definitions of processes and threads
  • Scheduling of threads
  • Thread synchronization and mutual exclusion
  • Deadlock problem

The origin of processes and threads

To explain this problem, from the classification and development process of the operating system, we usually contact more computers are time-sharing systems based on time slice scheduling, but in fact there are many other types of operating systems, time-sharing operation The system is not there from the beginning, and the concept of processes and threads is not there from the beginning.
The general development process of the operating system is as follows, we simply understand it:

  • Manual operation stage (no operating system in this stage)
  • Batch processing operating system
    • Single-channel batch processing system
    • Multichannel batch processing system
  • Time-sharing operating system
  • Real-time operating system
    • Hard real-time operating system
    • Soft real-time operating system
  • Network operating systems and distributed operating systems

The resource scheduling algorithms of different operating systems above are different. For example, the human-hard real-time system is not based on time slice scheduling, but on priority. We mainly focus on the transformation from single-channel operating system to multi-channel operating system.

For a single-channel operating system, there is no need for the concept of processes and threads, it is to execute jobs in order, and there is no parallel situation of multiple jobs over a period of time.

Of course, we can also see the problem of single-channel operating systems, that is, the utilization efficiency of various computer resources is very low. For example, when a job is waiting for I/O, the CPU is idle.

In order to improve the utilization efficiency of various resources, a multi-channel batch processing system is proposed, which is also a very important source of operating system complexity:

  • Because to be concurrent, there is a program switch, before switching from the options to select a run, the selection process is scheduling, there are a variety of different scheduling algorithms, such as FCFS, SJF, time slice and so on.
  • Because concurrency brings asynchrony, the execution order of each program is uncertain, so it may compete for critical resources. In order to avoid this contention, we propose mutual exclusion; another situation is that we need some Programs are executed in a certain order, so we propose the concept of synchronization.
  • Because of the proposal of mutual exclusion, there may be deadlock problems. For example, program A applies for P resources and waits for Q resources, while program B applies for Q resources. However, while waiting for P resources, a circular dependency is formed between A and B. And neither of them is willing to give up the acquired resources, then a deadlock is formed between A and B programs.

In order to describe the above scheduling, mutual exclusion, synchronization, and deadlock problems, we need to introduce a new concept to describe the state during program execution, and to save the context of execution at that time when the program switches. This concept is the process.

Then later we found that compared to other resources, CPU resources are scheduled very frequently, so we extracted a concept for CPU scheduling separately, called threads.

The concept of process and thread

So far, we have these concepts:

  • Homework: It can be understood as a program on our hard disk that has not been executed yet
  • Process: The basic unit of resource scheduling outside of the CPU. When we choose to execute a program, it is to apply for resources such as memory for the job, and then the process will start a thread by default to apply for CPU resources
  • Thread: The basic unit of CPU scheduling. Threads of the same process share the same set of resources, such as the same Memory Space, which means that data between threads of the same process can be directly modified

Threads are divided into kernel-level threads (KLT) and user-level threads (ULT). Kernel-level threads mean that there are really multiple threads in the operating system. The switching of threads requires the context switching of the operating system., the saving and loading of registers, etc., we did switch threads; and the meaning of user-level threads is that the operating system itself does not perceive thread switching at all. We simulated the switching of registers and so on within the thread. Each has its own benefits, the latter is sometimes called coroutine, and its benefits are that switching consumes less and does not require The disadvantage of using the operating system’s interrupt processing for context switching is that it cannot take advantage of multi-core processors, because no matter how many threads you have, it looks like one in the operating system.

Scheduling algorithm for threads

  • FCFS, First-Come First-Service algorithm, is an inalienable algorithm and is not suitable for time-sharing systems and real-time systems. On the surface, it is fair to all jobs, but if a long job arrives in the system first, it will be a short job that waits a long time
  • SJF, short job first algorithm. Bad for long jobs and may cause long jobs to be “hungry”
  • Priority scheduling algorithm, according to whether the high priority job arrives or interrupts the current job is divided into preemptive and non-preemptive, according to whether the priority can be changed at runtime into static priority and dynamic priority
  • High response ratio priority algorithm. Response ratio = (waiting time + requested service time)/requested service time
  • Time slice rotation scheduling algorithm.
  • Multi-level queue scheduling algorithm. Set multiple queues for different CPUs, each queue adopts a different scheduling algorithm
  • Multilevel feedback queue scheduling algorithm

Synchronization and mutual exclusion

Synchronization is a direct constraint relationship, such as A is to perform first than B, and mutual exclusion is an indirect constraint relationship, such as A and B have to use the only printer resources, A occupied, B can only block.
Basic method of mutual exclusion in critical area

Software methods

  1. Single marking method
  2. Double marking method
  3. Double mark inspection method
  4. Peterson’s Algorithm

Hardware implementation method

  1. Interrupt masking algorithm: turn off the interrupt, because the CPU can only switch processes when interrupted, and turn off the interrupt can directly prevent all process switching
  2. Hardware command method: TestAndSet

Mutual exclusion (mutex

A process acquires a lock when entering the critical section and releases the lock when exiting the critical section

Signal quantity

The semaphore mechanism is a powerful mechanism that can be used to solve mutual exclusion and synchronization problems. It can only be accessed by the two standard primitives wait and signal, and can also be recorded as P operations and V operations. There are two types:

  • Integer semaphore
1
2
3
4
5
6
7
8
wait(S) {
while(S <=0);
S = S - 1;
}

signal(S) {
S = S + 1;
}
  • Recording type semaphore
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
wait(semaphore S) {
S.value--;
if (S.value < 0) {
add this process to S.L;
block(S.L)
}
}

signal(semaphore S) {
S.value++;
if (S.value <= 0) {
remove a process P from S.L;
wakeup(P)
}
}

What does four cores and eight threads mean?

We always mention that a computer has four cores and eight threads. What is this concept?

As we just mentioned, whether it is a single-channel or multi-channel operating system, its concurrency is based on only one CPU core, that is to say, it can only have one program executing at the same time, and only one program counter.

We want to achieve the true meaning of multiple programs executed at the same time, the method is more than a few CPU cores, that is, the four cores here.

Theoretically, four cores could only have four threads in parallel. The reason for the emergence of four cores and eight threads was that two cores were simulated on one core, making the upper-level operating system think it had eight cores, but in fact it was still four cores. This is an implementation of computer virtualization technology.

Understanding multithreading in JS

Web

After understanding the concept of multi-threading, we can say JS multi-threaded Web Workers.

HTML5 introduces Web Workers, making JS support threads.

JS multithreading is OS-level, that is to say, JS multithreading is really multithreading, that is, the kernel-level thread mentioned above.

JS has no concept of thread synchronization

JS’s multi-threading cannot operate the DOM. There is no window object, and the data of each thread is independent. The data passed by the main thread to the child thread is copied by copying. The same child thread, the data given to the main thread is also copied by copying, rather than sharing the same memory area.

From this point of view, the multi-threading of JS does not belong to the same process, or there is an internal isolation mechanism

So there is basically nothing wrong with Web Workers.

In the main logic, the calls of fun1 and fun2 are connected together. It is an execution unit that has either not been executed yet or has to be executed in one go. After execution, execute setTimout append to the next one. Then because it has exceeded the 20ms set by setInterval, the setInterval function is executed immediately. Here it can be seen that the timing of setTimeout starts from, the timing starts when the logical unit is executed, and the timing starts when setInterval is executed on this line.

Single-threaded features such as asynchronous callback, asynchronous callback is Chrome own IO thread, processing, each request must have a thread to follow, Chrome limit the same, the domain can only send up to 6 requests at the same time

Chrome multithreading model

Let’s take a look at Chrome thread pattern from the click event

Every time a tab is opened, Chrome will create a process, the process is the container of the thread, and the Tab of the same domain name is the same process

First, the user clicks the mouse, and after the browser’s UI thread receives it, the message data is encapsulated as a mouse event and sent to the IO thread, which is then assigned to the rendering thread of the specific page. Among them, the IO thread and the UI thread are the browser’s threads, and the rendering thread is each page’s own thread.

If you are executing a time-consuming piece of JS code, the render thread in the render thread will be blocked, and the main thread will continue to receive messages from the IO thread and queue up, waiting for the render thread to process. That is to say, when the page is stuck, keep clicking the mouse, wait for the page to be idle, and the clicked event will continue to trigger.