12

我有一个测试:

html:

<div id="f1">Empty</div>
<div id="f2">Empty</div>

​

js:

var s1 = function() {
    for (i = 1; i < 1000000000; i++) {
        var b = i * i;
    }
    $('#f1').html('Set');
}

var s2 = function() {
    if ($('#f1').html() == 'Empty') {
        $('#f2').html('Multi Thread');
        return;            
    };
    $('#f2').html('One Thread');
}

setTimeout(s2,110);
setTimeout(s1,100);​

是否有任何真正的原因为什么 setTimeOut() 不在不同的线程中运行,而是像事件模型一样?

jsfiddle

4

8 回答 8

17

Javascript 本身不是多线程的,也不是非多线程的。但是,目前在主流浏览器中实现的 Javascript 的具体实现大多是单线程的。

此外,对于正确的多线程,该语言需要具有共享内存、锁、信号量和其他并发编程工具的功能,而当前定义的 JavaScript 没有这些功能(例如,无法描述并发 JS 线程如何控制谁可以更新 DOM 对象,这些对象当然是共享的,因为一个窗口中只有一个 DOM)。

有一些尝试让 JS 更加并行化——看看网络工作者、英特尔的 River Trail、谷歌的 HTML5工作等等。

于 2012-08-29T22:36:18.287 回答
4

eicto,在请求时setTimeout不会触发代码。 它将代码与之前的所有其他代码一起排队,内联,但它将其在行中的位置设置为至少请求的时间。

此外,大多数浏览器对最小超时都有硬性限制。
如果您请求 1 毫秒的超时,那么在大多数浏览器中,您很可能会在 10 毫秒到 15 毫秒后收到您的请求。

所有 JS 与 DOM 的交互,实际上,几乎单个页面所做的所有事情,都发生在一个线程上,除了自定义浏览器扩展和一些新的 API(如 webworkers)。

这就是为什么大型项目需要考虑页面上的其他所有内容,以及为什么所有内容都需要异步的原因。

因为setTimeoutis 不是 asleep并且它不会在它被cron编辑的确切微秒内返回... ...它在事件堆栈上放置一个回调,时间不早于您指定的时间。

于 2012-09-27T20:59:21.450 回答
4

浏览器中的 Javascript 实现有很多设计决策,假设它只有单线程访问浏览器 DOM 和其他全局变量/属性。这使得使用它进行编程不太可能导致问题,但引入了一些必须处理的限制。

该语言本身完全具备多线程能力,我们已经在 WebWorkers 和该语言的某些服务器实现中看到了这一点。但是,每当您使用多个线程并尝试读取/写入在多个线程之间共享的变量或属性时,必须使用保护设备(如互斥锁)以允许对这些共享资源进行可靠访问。这使得如何进行这种编程变得非常复杂,并且浏览器中的 Javascript 决定不需要那种程度的理解来可靠地对其进行编程。

对于任何做过多线程编程的人来说,它可以很强大,但是很容易引入难以发现的错误。那些负责浏览器中 Javascript 的人决定应该完全避免这种难度和由此产生的错误类型。

即使现在使用 WebWorkers,WebWorker 和主 javascript 线程之间也没有共享资源。两者必须通过消息传递系统进行通信,这是一种强制安全的万无一失的方式。而且,结果是无法从 WebWorker 访问 DOM。相反,如果您希望更改 DOM,则必须向单个主线程发布消息并要求 IT 更新 DOM。主线程只有在完成其他事情时才会收到该消息(它是单线程的)。

DOM 现在也很可能已经花费了数亿年作为一个仅为单线程访问而设计的结构,因此设计和实现一种从多个线程访问它的方法(并修复所有导致的错误)将是一项艰巨的任务在该实施中)。

于 2012-08-29T22:52:12.287 回答
2

Javascript 不支持多线程,因为您在浏览器中的解释器是单线程

于 2012-08-29T22:33:13.503 回答
1

JavaScript 不是多线程的,但即使是 setTimeout 也是同步的。setTimeout 和 setInterval 由正确的 JavaScript 语言之外的浏览器提供,它提供了访问该语言的外部方法,例如事件执行。当人们将 JavaScript 称为异步或多线程语言时,这很可能是他们所指的,因为多个外部访问点(例如大量计时器或事件执行)可以同时发生,每个访问点都会在内存中生成一个对解释器的唯一访问点。这正是 Node.js 的开发人员在对 JavaScript 提出此类声明时所指的内容。

这意味着对各种隔离线程的多个外部访问可能会导致 UI 中的冲突,因为模拟的多线程效果可能会导致浏览器输出中的冲突,其中只有一个文档对象代表整个页面。这就是为什么 setInterval 的间隔很短通常被认为是不安全的。setInterval 是完全异步的,即使在前一个时间间隔内的执行还没有结束,它也会按照提供的时间间隔执行。这种碰撞就是我所说的故障转移,因为下一个时间间隔是执行的代码会超过之前的执行,如果您的代码需要访问 DOM 或使用闭包,您可能会遇到问题。为了安全起见,建议使用递归 setTimeout,

于 2012-08-29T23:00:49.567 回答
0

Mozilla 确实支持 Javascript 中的多线程 - 只要您不想从多个线程进行 UI 工作。我的删除重复消息 (Alternatve)扩展的早期版本是多线程的。

在我的扩展中查看我自己的关于这个问题的错误页面,或者更好的是,这个关于在 Mozilla 中使用工作线程的页面。eicto,您可以使用后台线程很好地实现您的代码。

于 2012-09-27T20:44:55.600 回答
0

Javascript 不是多线程的。

HTML5 将赋予 javascript 多线程功能。

于 2012-08-29T22:33:17.953 回答
-1

等待给定的时间后,方法(s1,s2)的执行仍然发生在javascript线程本身(单线程)中。

s2 等待 s1 的原因。

于 2020-01-28T13:17:51.377 回答