JavaScript 싱글스레딩에 대한 자세한 소개(그림)
프로세스와 스레드는 운영체제의 개념입니다. 프로세스는 애플리케이션의 실행 인스턴스입니다. 각 프로세스는 개인 가상 주소 공간, 코드, 데이터 및 기타 시스템 리소스로 구성되며, 프로세스는 작업 중에 시스템 리소스(예: 독립 메모리 영역)를 생성하고 사용합니다. . , 프로세스가 종료되면 이러한 리소스도 삭제됩니다. 스레드는 프로세스 내의 독립적인 실행 단위이며 프로세스 리소스는 서로 다른 스레드 간에 공유될 수 있으므로 멀티스레딩의 경우 중요한 리소스에 대한 접근 제어에 특별한 주의가 필요합니다. 시스템은 프로세스를 생성한 후 해당 프로세스를 실행하는 메인 스레드를 시작합니다. 프로세스의 수명 주기는 메인 스레드의 수명 주기와 일치합니다. 메인 스레드의 종료는 프로세스의 종료 및 소멸을 의미합니다. 메인 스레드는 시스템 프로세스에 의해 생성되며, 사용자는 다른 스레드를 독립적으로 생성할 수도 있습니다. 이 일련의 스레드는 동일한 프로세스에서 동시에 실행됩니다.
분명히 멀티 스레드 작업에서 애플리케이션의 병렬 처리가 가능하므로 CPU 사용률이 높아져 전체 애플리케이션의 성능과 처리량이 향상됩니다. 특히 이제 많은 언어가 멀티 코어 병렬 처리 기술을 지원하므로 JavaScript가 단일 스레드에서 실행되는 이유는 무엇입니까?또한 JavaScript는 단일 스레드이므로 특정 시간에 특정 작업 하나만 실행할 수 있으며 다른 작업의 실행은 차단됩니다. 그러면 I/O와 같이 시간이 많이 걸리는 작업의 경우 후속 작업을 계속하기 전에 해당 작업이 완료될 때까지 기다릴 필요가 없습니다. 이러한 작업이 완료되기 전에 JavaScript는 계속해서 다른 작업을 수행할 수 있습니다. 이러한 시간이 많이 소요되는 작업이 완료되면 해당 처리가 콜백 형태로 수행됩니다. 비동기식 및 콜백은 JavaScript의 고유한 기능입니다. 물론, 시간이 많이 걸리는 불가피한 작업(예: 과도한 작업, 다중 루프)을 위해 HTML5는 Worker 클래스를 사용하여 현재 JavaScript 실행 메인 스레드에 추가 스레드를 생성하는 Web Worker를 제안합니다. 특정 JavaScript 파일을 로드하고 실행하면 이 새 스레드와 JavaScript 메인 스레드는 서로 영향을 주거나 실행을 차단하지 않으며 Web Worker는 이 새 스레드와 JavaScript 메인 스레드 간의 데이터 교환을 위한 인터페이스인 postMessage 및 onMessage 이벤트를 제공합니다. 하지만 HTML5 Web Worker에서는 DOM을 조작할 수 없습니다. DOM 운영이 필요한 모든 작업은 JavaScript 메인 스레드에 맡겨 실행해야 합니다. 따라서 HTML5 Web Worker가 도입되었지만 JavaScript의 단일 스레드 특성은 다음과 같습니다. 아직도 변하지 않았습니다. 동시성 모드 및 이벤트 루프JavaScript에는 "이벤트 루프"를 기반으로 하는 동시성 모델이 있습니다. 아, 동시성? 자바스크립트는 싱글스레드라고 하지 않나요? 예, 실제로는 단일 스레드이지만 동시성과 병렬성에는 차이가 있습니다. 전자가 논리적 동시성이라면, 후자는 물리적 동시성이다. 따라서 단일 코어 프로세서도 동시성을 달성할 수 있습니다. 동시성과 병렬성 병렬은 누구나 이해하기 쉬운 말로, 소위 '동시성'이란 둘 이상의 사건이 동시에 일어나는 것을 의미합니다. 위의 첫 번째 표에서 보듯이, 컴퓨터 시스템에는 CPU가 1개밖에 없기 때문에 "마이크로" 관점에서 세 개의 프로그램 ABC가 CPU를 교대로 사용하지만 교대 시간이 매우 짧고 사용자가 이를 알아차릴 수 없어 동시성을 형성합니다. "매크로" 감각이 작동합니다.사실 이는 목적과 관련이 있습니다. 브라우저 스크립팅 언어인 JavaScript의 주요 목적은 사용자와 상호 작용하고 DOM을 조작하는 것입니다. 이러한 DOM이 멀티스레드 방식으로 작동되는 경우 작업 충돌이 발생할 수 있습니다. DOM 요소를 동시에 작동하는 두 개의 스레드가 있다고 가정합니다. 스레드 1에서는 브라우저가 DOM을 삭제해야 하고 스레드 2에서는 DOM 스타일을 수정해야 합니다. 이때 브라우저는 어떤 스레드를 사용할지 결정할 수 없습니다. 물론 이러한 충돌을 해결하기 위해 브라우저에 "잠금" 메커니즘을 도입할 수 있지만 이로 인해 복잡성이 크게 증가하므로 JavaScript는 탄생 이후 단일 스레드 실행을 선택했습니다.
런타임 개념
Stack(스택)
다음은 JavaScript가 실행하는 작업입니다. 각 작업을 프레임 스택이라고 합니다.
function f(b){ var a = 12; return a+b+35; } function g(x){ var m = 4; return f(m*x); } g(21);
위 코드가 g
을 호출하면 g
의 매개변수와 지역 변수가 포함된 스택의 첫 번째 프레임이 생성됩니다. g
이 f
을 호출하면 두 번째 프레임이 생성되어 첫 번째 프레임 위에 배치됩니다. 물론 이 프레임에는 f
의 매개변수와 지역 변수도 포함됩니다. f
이 반환되면 해당 프레임이 스택에서 사라집니다. 마찬가지로 g
가 반환되면 스택은 비어 있습니다(스택의 구체적인 정의는 LIFO(후입선출)입니다).
힙
객체가 할당되는 메모리의 구조화되지 않은 대규모 영역을 나타내는 데 사용되는 이름입니다.
큐(queue)
JavaScript 런타임에는 처리할 일련의 작업으로 구성된 작업 큐가 포함되어 있습니다. 각 작업에는 해당 기능이 있습니다. 스택이 비어 있으면 작업 대기열에서 작업을 가져와 처리합니다. 이 프로세스는 작업과 관련된 일련의 함수를 호출합니다(따라서 초기 스택 프레임 생성). 작업이 처리되면 스택은 다시 비게 됩니다. (큐의 특징은 선입선출(FIFO)입니다.)
설명과 이해를 돕기 위해 다음과 같은 규칙을 따릅니다.
스택 스택이 메인 스레드입니다
대기열 대기열은 작업 대기열입니다(실행을 위해 메인 스레드에 대한 예약을 기다리는 중)
자, 위의 지식 포인트는 JavaScript 런타임과 관련된 개념을 명확히 하는 데 도움이 됩니다. 후속 분석.
이벤트 루프
유사한 방식으로 구현되었기 때문에 이벤트 루프라고 합니다.
while(queue.waitForMessage()){ queue.processNextMessage(); }
위에서 언급했듯이 "작업 큐"는 이벤트 큐입니다. I/O 장치가 작업을 완료하거나 사용자가 이벤트(이벤트가 콜백 함수를 지정함)를 트리거하면 관련 이벤트 처리 기능이 "작업 대기열"에 들어가고, 메인 스레드가 유휴 상태일 때 "작업의 세 번째 스레드가 됩니다. 대기열"이 예약됩니다. 보류 중인 작업(FIFO)입니다. 물론 타이머의 경우 지정된 시간에 도달하면 해당 작업이 "작업 대기열"의 끝에 삽입됩니다.
"완료까지 실행"
작업이 실행될 때마다 다른 작업이 실행됩니다. 즉, 함수가 실행되면 대체될 수 없으며 다른 코드가 실행되기 전에 완료됩니다.
물론 이는 이벤트 루프의 단점이기도 합니다. 작업을 완료하는 데 너무 오랜 시간이 걸리면 애플리케이션이 사용자 상호 작용(예: 클릭 이벤트)을 제때에 처리할 수 없으며 심지어 애플리케이션이 충돌할 수도 있습니다. 더 나은 해결책은 작업 완료 시간을 단축하거나 작업을 여러 작업으로 나누어 실행하는 것입니다.
차단하지 않음
JavaScript는 다른 언어와 다릅니다. 이벤트 루프의 특징 중 하나는 절대 차단하지 않는다는 것입니다. I/O 작업은 일반적으로 이벤트 및 콜백 함수를 통해 처리됩니다. 따라서 애플리케이션이 indexedDB 또는 XHR 비동기 요청이 반환되기를 기다리는 동안에도 다른 작업(예: 사용자 입력)을 처리할 수 있습니다.
경고나 동기 XHR과 같은 예외가 있지만 이를 피하는 것이 모범 사례로 간주됩니다. 예외에 대한 예외가 존재한다는 점에 유의하십시오(그러나 일반적으로 다른 이유보다는 구현 오류로 인해 발생함).
타이머
타이머의 일부 개념
위에서 언급한 것처럼 지정된 시간에 도달하면 타이머는 "작업 대기열"의 끝에 해당 콜백 함수를 삽입합니다. " . 이것이 "타이머" 기능이다.
타이머에는 setTimeout과 setInterval이라는 두 가지 메소드가 포함되어 있습니다. 두 번째 매개변수는 콜백 함수가 지연되어야 하는 시간(밀리초)을 지정합니다.
두 번째 매개변수에 관해 주의할 사항은 다음과 같습니다.
두 번째 매개변수가 기본값인 경우 기본값은 0입니다.
지정된 값이 4밀리초 미만인 경우 4ms로 늘립니다(HTML5 표준에서는 4ms, 2010년 이전 브라우저에서는 10ms로 지정됨).
이해하시면 위의 지식을 바탕으로 다음 코드는 문제가 되지 않습니다.
console.log(1); setTimeout(function(){ console.log(2); },10); console.log(3); // 输出:1 3 2
타이머에 대한 심층적인 이해
Zero Delay setTimeout(func, 0)
지연이 0이라고 해서 콜백 함수가 즉시 실행되는 것은 아닙니다. 이는 메인 스레드가 현재 유휴 상태인지 여부와 "작업 대기열"에서 그 앞에 대기 중인 작업에 따라 달라집니다.
다음 코드를 보세요:
(function () { console.log('this is the start'); setTimeout(function cb() { console.log('this is a msg from call back'); }); console.log('this is just a message'); setTimeout(function cb1() { console.log('this is a msg from call back1'); }, 0); console.log('this is the end'); })(); // 输出如下: this is the start this is just a message this is the end undefined // 立即调用函数的返回值 this is a msg from callback this is a msg from a callback1
setTimeout(func, 0)의 역할
브라우저가 렌더링하도록 합니다. 현재 변경 사항(많은 브라우저 UI 렌더링 및 js 실행이 스레드에 배치되고 스레드 차단으로 인해 인터페이스 업데이트 및 렌더링이 실패함)
"스크립트가 실행 중인지 재평가합니다. 너무 길다" 경고
실행 순서 변경
다음 코드를 다시 살펴보세요.
<button id='do'> Do long calc!</button> <p id='status'></p> <p id='result'></p> $('#do').on('click', function(){ $('#status').text('calculating....');// 此处会触发redraw事件,但会放到队列里执行,直到long()执行完。 // 没设定定时器,用户将无法看到“calculating...” long();// 执行长时间任务,造成阻塞 // 设定了定时器,用户就如期看到“calculating...” //setTimeout(long,50);// 大约50ms后,将耗时长的long回调函数插入“任务队列”末尾,根据先进先出原则,其将在redraw之后被调度到主线程执行 }); function long(){ var result = 0 for (var i = 0; i<1000; i++){ for (var j = 0; j<1000; j++){ for (var k = 0; k<1000; k++){ result = result + i+j+k } } } $('#status').text('calclation done'); // 在本案例中,该语句必须放到这里,这将使它与回调函数的行为类似 }
원본과 복제본의 차이점 setInterval
setTimeout이 setInterval의 효과를 모방할 수 있다는 것은 누구나 알 수 있습니다. 다음 코드의 차이점을 살펴보겠습니다.
// 利用setTimeout模仿setInterval setTimeout(function(){ /* 执行一些操作. */ setTimeout(arguments.callee, 10); }, 1000); setInterval(function(){ /* 执行一些操作 */ }, 1000);
아마도 여러분은 이렇게 생각할 것입니다. 차이가 없습니다. 실제로 콜백 함수에서의 연산이 짧은 시간이 걸릴 경우에는 둘 사이의 차이를 볼 수 없습니다.
其实:上面案例中的 setTimeout 总是会在其回调函数执行后延迟 10ms(或者更多,但不可能少)再次执行回调函数,从而实现setInterval的效果,而 setInterval 总是 10ms 执行一次,而不管它的回调函数执行多久。
所以,如果 setInterval 的回调函数执行时间比你指定的间隔时间相等或者更长,那么其回调函数会连在一起执行。
你可以试试运行以下代码:
var counter = 0; var initTime = new Date().getTime(); var timer = setInterval(function(){ if(counter===2){ clearInterval(timer); } if(counter === 0){ for(var i = 0; i < 1990000000; i++){ ; } } console.log("第"+counter+"次:" + (new Date().getTime() - initTime) + " ms"); counter++; },1000);
我电脑Chrome浏览器的输入如下:
第0次:2007 ms 第1次:2013 ms 第2次:3008 ms
浏览器
浏览器不是单线程的
上面说了这么多关于JavaScript是单线程的,下面说说其宿主环境——浏览器。
浏览器的内核是多线程的,它们在内核制控下相互配合以保持同步,一个浏览器至少实现三个常驻线程:
javascript引擎线程 javascript引擎是基于事件驱动单线程执行的,JS引擎一直等待着任务队列中任务的到来,然后加以处理,浏览器无论什么时候都只有一个JS线程在运行JS程序。
GUI渲染线程 GUI渲染线程负责渲染浏览器界面,当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。但需要注意GUI渲染线程与JS引擎是互斥的,当JS引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
浏览器事件触发线程 事件触发线程,当一个事件被触发时该线程会把事件添加到“任务队列”的队尾,等待JS引擎的处理。这些事件可来自JavaScript引擎当前执行的代码块如setTimeOut、也可来自浏览器内核的其他线程如鼠标点击、AJAX异步请求等,但由于JS是单线程执行的,所有这些事件都得排队等待JS引擎处理。
在Chrome浏览器中,为了防止因一个标签页奔溃而影响整个浏览器,其每个标签页都是一个进程。当然,对于同一域名下的标签页是能够相互通讯的,具体可看 浏览器跨标签通讯。在Chrome设计中存在很多的进程,并利用进程间通讯来完成它们之间的同步,因此这也是Chrome快速的法宝之一。对于Ajax的请求也需要特殊线程来执行,当需要发送一个Ajax请求时,浏览器会开辟一个新的线程来执行HTTP的请求,它并不会阻塞JavaScript线程的执行,当HTTP请求状态变更时,相应事件会被作为回调放入到“任务队列”中等待被执行。
看看以下代码:
document.onclick = function(){ console.log("click") } for(var i = 0; i< 100000000; i++);
解释一下代码:首先向document注册了一个click事件,然后就执行了一段耗时的for循环,在这段for循环结束前,你可以尝试点击页面。当耗时操作结束后,console控制台就会输出之前点击事件的”click”语句。这视乎证明了点击事件(也包括其它各种事件)是由额外单独的线程触发的,事件触发后就会将回调函数放进了“任务队列”的末尾,等待着JavaScript主线程的执行。
总结
JavaScript是单线程的,同一时刻只能执行特定的任务。而浏览器是多线程的。
异步任务(各种浏览器事件、定时器等)都是先添加到“任务队列”(定时器则到达其指定参数时)。当Stack栈(JS主线程)为空时,就会读取Queue队列(任务队列)的第一个任务(队首),然后执行。
JavaScript为了避免复杂性,而实现单线程执行。而今JavaScript却变得越来越不简单了,当然这也是JavaScript迷人的地方。
위 내용은 JavaScript 싱글스레딩에 대한 자세한 소개(그림)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











WebSocket 및 JavaScript를 사용하여 온라인 음성 인식 시스템을 구현하는 방법 소개: 지속적인 기술 개발로 음성 인식 기술은 인공 지능 분야의 중요한 부분이 되었습니다. WebSocket과 JavaScript를 기반으로 한 온라인 음성 인식 시스템은 낮은 대기 시간, 실시간, 크로스 플랫폼이라는 특징을 갖고 있으며 널리 사용되는 솔루션이 되었습니다. 이 기사에서는 WebSocket과 JavaScript를 사용하여 온라인 음성 인식 시스템을 구현하는 방법을 소개합니다.

WebSocket과 JavaScript: 실시간 모니터링 시스템 구현을 위한 핵심 기술 서론: 인터넷 기술의 급속한 발전과 함께 실시간 모니터링 시스템이 다양한 분야에서 널리 활용되고 있다. 실시간 모니터링을 구현하는 핵심 기술 중 하나는 WebSocket과 JavaScript의 조합입니다. 이 기사에서는 실시간 모니터링 시스템에서 WebSocket 및 JavaScript의 적용을 소개하고 코드 예제를 제공하며 구현 원칙을 자세히 설명합니다. 1. 웹소켓 기술

JavaScript 및 WebSocket을 사용하여 실시간 온라인 주문 시스템을 구현하는 방법 소개: 인터넷의 대중화와 기술의 발전으로 점점 더 많은 레스토랑에서 온라인 주문 서비스를 제공하기 시작했습니다. 실시간 온라인 주문 시스템을 구현하기 위해 JavaScript 및 WebSocket 기술을 사용할 수 있습니다. WebSocket은 TCP 프로토콜을 기반으로 하는 전이중 통신 프로토콜로 클라이언트와 서버 간의 실시간 양방향 통신을 실현할 수 있습니다. 실시간 온라인 주문 시스템에서는 사용자가 요리를 선택하고 주문을 하면

WebSocket과 JavaScript를 사용하여 온라인 예약 시스템을 구현하는 방법 오늘날의 디지털 시대에는 점점 더 많은 기업과 서비스에서 온라인 예약 기능을 제공해야 합니다. 효율적인 실시간 온라인 예약 시스템을 구현하는 것이 중요합니다. 이 기사에서는 WebSocket과 JavaScript를 사용하여 온라인 예약 시스템을 구현하는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 1. WebSocket이란 무엇입니까? WebSocket은 단일 TCP 연결의 전이중 방식입니다.

JavaScript 및 WebSocket: 효율적인 실시간 일기 예보 시스템 구축 소개: 오늘날 일기 예보의 정확성은 일상 생활과 의사 결정에 매우 중요합니다. 기술이 발전함에 따라 우리는 날씨 데이터를 실시간으로 획득함으로써 보다 정확하고 신뢰할 수 있는 일기예보를 제공할 수 있습니다. 이 기사에서는 JavaScript 및 WebSocket 기술을 사용하여 효율적인 실시간 일기 예보 시스템을 구축하는 방법을 알아봅니다. 이 문서에서는 특정 코드 예제를 통해 구현 프로세스를 보여줍니다. 우리

JavaScript 튜토리얼: HTTP 상태 코드를 얻는 방법, 특정 코드 예제가 필요합니다. 서문: 웹 개발에서는 서버와의 데이터 상호 작용이 종종 포함됩니다. 서버와 통신할 때 반환된 HTTP 상태 코드를 가져와서 작업의 성공 여부를 확인하고 다양한 상태 코드에 따라 해당 처리를 수행해야 하는 경우가 많습니다. 이 기사에서는 JavaScript를 사용하여 HTTP 상태 코드를 얻는 방법과 몇 가지 실용적인 코드 예제를 제공합니다. XMLHttpRequest 사용

사용법: JavaScript에서 insertBefore() 메서드는 DOM 트리에 새 노드를 삽입하는 데 사용됩니다. 이 방법에는 삽입할 새 노드와 참조 노드(즉, 새 노드가 삽입될 노드)라는 두 가지 매개 변수가 필요합니다.

Golang의 단일 스레드 기능 및 장점 인터넷 및 모바일 애플리케이션의 급속한 발전으로 고성능, 동시성 프로그래밍 언어에 대한 수요가 증가하고 있습니다. 이러한 배경에서 Go 언어(줄여서 Golang)는 Google에서 개발하여 2009년에 처음 출시되었으며 개발자들 사이에서 빠르게 인기를 얻었습니다. Golang은 정적 타이핑과 동시 설계를 사용하는 오픈 소스 프로그래밍 언어입니다. 가장 큰 장점 중 하나는 단일 스레드 기능입니다. Golang은 Goroutine의 동시성 모델을 채택합니다.
