Process & Thread

Processes are the smallest unit of resource allocation

Threads are the smallest unit of CPU scheduling

Here’s a simple analogy:

Process = train, thread = car

  • Threads move under a process (pure cars cannot run)

  • A process can contain more than one thread (a train can have more than one car)

  • It is difficult to share data between different processes (passengers on one train can hardly change to another train, such as station transfer). It is easy to share data between different threads in the same process (it is easy to change from car A to car B).

  • Processes consume more computer resources than threads (using more trains than cars)

  • Processes do not interact with each other, the failure of one thread will result in the failure of the entire process (one train will not affect another train, but if the middle car on one train catches fire, it will affect all trains)

Browsers are multi-process

Opening a web page in the browser is like opening a new process. Of course, the browser will sometimes merge multiple processes into the same process for its own optimization (e.g. opening multiple blank pages).

Browser multiprocesses include:

The browser rendering process is multi-threaded.

1.GUI rendering thread

Responsible for rendering browser interfaces, parsing HTML, CSS, building DOM trees and RenderObject trees, layout and drawing, etc.

2.JS engine threads

Also known as the JS kernel, it handles Javascript scripts. (For example V8 engine)

3. The event triggers the thread

When the JS engine executes a code block such as setTimeOut (or other threads from the browser kernel, such as mouse clicks, AJAX asynchronous requests, etc.), Added to the event thread will correspond to the task When the corresponding event in line with the trigger condition is triggered, the thread will add events to the pending queue the next morning, waiting for the JS engine processing note that because of JS single-threaded relationship, so all the pending event in the queue have to queue for JS engine processing (when JS engine idle to perform)

4. Trigger the thread periodically

SetInterval and setTimeout threads

5. Asynchronous HTTP request threads

After the XMLHttpRequest connects, the browser opens a new thread request

Conclusion:

GUI rendering threads are mutually exclusive with JS engine threads

Since JavaScript is DOM manipulable, if you render the interface while modifying these element attributes (i.e., the JS thread and the UI thread are running at the same time), the element data obtained before and after the render thread may not be consistent.

Therefore, to prevent unexpected results from rendering, the browser sets the GUI rendering thread and the JS engine to be mutually exclusive. The GUI thread is suspended when the JS engine executes, and GUI updates are stored in a queue until the JS engine thread is idle.

Similarly, JS can block pages if it takes too long to execute.

Js is single threaded

One of the hallmarks of the JavaScript language is single-threaded, which means you can only do one thing at a time. So why can’t JavaScript have multiple threads? It’s more efficient.

The single thread of JavaScript, relative to its purpose. As a browser scripting language, JavaScript’s primary purpose is to interact with users and manipulate the DOM. This means that it has to be single-threaded, which can cause complex synchronization problems. For example, if there are two threads of JavaScript at the same time, one thread adds content to a DOM node, and the other thread removes that node, which thread should the browser use?

So, to avoid complexity, JavaScript has been single-threaded since its inception.

In order to make use of the computing power of multi-core CPU, HTML5 proposes the Web Worker standard, which allows JavaScript scripts to create multiple threads, but the child threads are completely controlled by the main thread and cannot operate DOM. So, this new standard doesn’t change the single-threaded nature of JavaScript.

Js execution stack

Each function call has its own execution context. When the code execution stream enters a function, the execution context of the function is pushed onto a stack of execution contexts. After the function completes execution, the execution context stack pops the function context, returning control to the previous execution context. Execution stack follows the first in, last out principle

Task queue: Synchronous task & asynchronous task

All tasks can be classified into synchronous tasks and asynchronous tasks

Synchronization tasks: Tasks to be executed immediately. Synchronization tasks are queued on the main thread to form an execution stack

Asynchronous tasks: Asynchronously executed tasks, such as Ajax network requests and setTimeout, are all asynchronous tasks. Asynchronous tasks are coordinated through the mechanism of task Event Queue

js Event Loop

  • All tasks run on the main thread, and JS code is executed by adding functions to the execution stack
  • A synchronous task executes directly and an asynchronous task suspends this event to continue executing other tasks in the stack
  • When an asynchronous Event returns a result, JS adds the Event to a separate Queue from the current execution stack, the Event Queue
  • Tasks placed on the event queue do not execute immediately but wait until all tasks in the execution stack have completed execution
  • When the main thread is idle, the main thread looks to see if there are any tasks in the event queue. If there is a main thread, it takes the first event and puts the corresponding callback on the execution stack, and then executes the synchronization code
  • This process is called an Event Loop.

Take a look at the picture below (paraphrase from Philip Roberts’ talk, Help, I’m Stuck in an Event-Loop).

And:

Microtasks & macro tasks

Different asynchronous tasks are divided into two categories: Micro tasks and Macro tasks.

  • Microtasks: Promise.then, Process,nextTick(Node.js), MutationObserver
  • Macrotasks: setTimeout, setInterval, I/O, Events, postMessage, setImmediate, requestAnimationFrame, UI rendering, Script

Each time the main thread execution stack is empty, the engine processes the microtask queue first, completes all tasks in the microtask queue, and then processes the macro task

The last

Try a classic one

console.log('script start')

async function async1() {
  await async2()
  console.log('async1 end')}async function async2() {
  console.log('async2 end')
}
async1()

setTimeout(function() {
  console.log('setTimeout')},0)

new Promise(resolve= > {
  console.log('Promise')
  resolve()
})
  .then(function() {
    console.log('promise1')
  })
  .then(function() {
    console.log('promise2')})console.log('script end')
// script start async2 end Promise script end async1 end promise1 promise2 setTimeout
Copy the code

reference

  • The way of the front-end interview
  • More on the Event Loop
  • Understand Event Loop for the last time