由于JavaScript是单线程的,因此HTML5中的Web工作人员如何进行multithreading?
我一直在阅读关于HTML5中的Web工作者,但我知道JavaScript是单线程的。
我的问题是:
networking工作者如何进行multithreading工作呢? 或者如果它不是真正的multithreading,他们如何模拟? 在这里我不明白。
正如几个意见已经指出的那样,工人真的是multithreading的。
有些问题可能有助于澄清你的想法:
- JavaScript是一种语言,它没有定义线程模型,它不一定是单线程的
- 大多数浏览器历来都是单线程的(尽pipe这种情况正在迅速变化: IE , Chrome , Firefox ),大多数JavaScript实现都发生在浏览器
- Web Workers不是JavaScript的一部分,它们是可以通过JavaScript访问的浏览器function
你产生一个.js文件作为一个“工人”,它运行在一个单独的线程进程。 您可以在它和“主”线程之间来回传递JSON数据。 尽pipe如此,工作人员不能访问DOM等特定的东西。
所以,如果你想解决复杂的math问题,你可以让用户input东西到浏览器中,把这些variables传递给工作者,让它在后台进行计算,而在主线程中让用户做其他的东西,或者显示一个进度条或者其他的东西,然后当工作完成后,它将答案传回来,并打印到页面上。 您甚至可以asynchronous执行多个问题,并在完成时按顺序传回。 很简约!
有点晚了,但我只是问自己同样的问题,我想出了以下答案:
浏览器中的Javascript总是单线程的 ,并发访问variables通常不是问题; 除了webworkers ,它们实际上是在单独的线程中运行, 并且访问variables的并发访问必须以某种明确的方式处理 。
我不是一个JavaScript忍者,但我也知道浏览器中的JavaScript是作为一个单线程进程提供的。
支持这个假设的一个简单的事实是,在JavaScript中编程时,您不必关心对共享variables的并发访问 。 每个开发人员,甚至不考虑问题,就像每次访问variables是一致的一样写代码。
换句话说,你不需要担心所谓的内存模型 。
实际上,没有必要看Web工作者涉及JavaScript中的并行处理。 想一想(asynchronous)的AJAX请求。 并认为你会不小心地处理并发访问variables:
var counter = 0; function asyncAddCounter() { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4) { counter++; } }; xhttp.open("GET", "/a/remote/resource", true); xhttp.send(); } asyncAddCounter(); counter++;
在这个过程结束时, counter
的价值是多less? 它是2
。 它并不重要,它是“同时”读写,它永远不会导致1
。 这意味着访问counter
始终是一致的。 如果两个线程同时访问这个值,它们都可以通过读0
开始,最后写入1
。
在浏览器中,ajax请求可能会为其实际的数据提取生成一个新的线程,但其内部工作不在JavaScript API的范围之内(浏览器允许您在JavaScript指令方面进行控制)。 就开发人员而言,新networking请求的结果由主线程处理。
这是通过使用事件循环 ,而不是multithreading来实现的。 这对几个浏览器来说是这样,对于Node.js来说也是如此。 以下是一些参考资料,在某些情况下已经过时了,但我想现在仍然保留主要观点。
- Firefox: 并发模型和事件循环 – JavaScript | MDN
- Chrome在某些操作系统中使用libevent 。
- IE: 了解事件模型(Internet Explorer)
这就是为什么JavaScript被说成是事件驱动但不是multithreading的原因。
至于WebWorkers, 它们是 JavaScript API,可让开发人员控制multithreading进程。
因此,它们提供了一种读取和写入价值的方式,其中包括以下几种方式:
- 您通过结构化克隆将数据推送到Web Worker(这意味着新线程将读取数据): 结构化克隆algorithm – Web API | MDN 。 本质上没有“共享”variables,而是给新线程一个新的对象副本。
- 您通过传输值的所有权将数据推送到Web工作人员: Transferable – Web API | MDN 。 这意味着只有一个线程可以随时读取其值。
- 对于Web工作者返回的结果(他们如何“写”),主线程在提示时访问结果(例如,使用
thisWorker.onmessage = function(e) {console.log('Message ' + e.data + ' received from worker');}
)。 必须通过通常的事件循环,我必须假设。 - 主线程和Web工作者访问一个真正的共享内存
SharedArrayBuffer
,它是使用Atomic
函数线程安全地访问的。 我发现这篇文章清楚地显示了这一点: JavaScript:从工作者到共享内存 - 注意:webworkers不能访问DOM,这是真正的共享!
浏览器踢你想要执行的JavaScript线程。 所以它是一个真正的线程,与这个networking工作者的事情,你的JS不再是单线程的。