Javascript 需要互斥对象吗?

我看过这个链接: 在 JavaScript 中实现互斥锁。 另一方面,我读到 javascript 中没有线程,但这到底意味着什么呢?

当事件发生时,它们在代码中的哪个位置可以中断?

如果 JS 中没有线程,我是否需要在 JS 中使用互斥对象?

具体来说,我想知道使用 setTimeout()XmlHttpRequestonreadystatechange调用的函数对全局可访问变量的影响。

74376 次浏览

JavaScript 是单线程的... ... 尽管 Chrome 可能是一个新的怪兽(我认为它也是单线程的,但是每个标签页都有它自己的 JavaScript 线程... ... 我还没有详细研究它,所以不要在那里引用我的话)。

However, one thing you DO need to worry about is how your JavaScript will handle multiple ajax requests coming back in not the same order you send them. So, all you really need to worry about is make sure your ajax calls are handled in a way that they won't step on eachother's feet if the results come back in a different order than you sent them.

这也适用于暂停。

当 JavaScript 发展成多线程时,可能会担心互斥锁之类的问题... ..。

Javascript 被定义为 再入者语言,这意味着没有线程暴露给用户,实现中可能有线程。像 setTimeout()和异步回调这样的函数需要等到脚本引擎休眠之后才能运行。

这意味着在处理下一个事件之前,必须完成事件中发生的所有事情。

也就是说,如果代码在触发异步事件和调用回调之间期望某个值不变,那么可能需要一个互斥锁。

例如,如果你有一个数据结构,你点击一个按钮,它发送一个 XmlHttpRequest,它调用一个回调,以破坏性的方式改变数据结构,你有另一个按钮,直接改变相同的数据结构,当事件被触发和回调执行之间,用户可以点击和更新数据结构,然后失去回调的价值。

While you could create a race condition like that it's very easy to prevent that in your code since each function will be atomic. It would be a lot of work and take some odd coding patterns to create the race condition in fact.

事件是有信号的,但 JavaScript 的执行仍然是单线程的。

My understanding is that when event is signaled the engine stops what it is executing at the moment to run event handler. After the handler is finished, script execution is resumed. If event handler changed some shared variables then resumed code will see these changes appearing "out of the blue".

如果你想“保护”共享数据,简单的布尔标志就足够了。

JavaScript,即 语言,可以像您希望的那样是多线程的,但是 JavaScript 引擎的浏览器嵌入只运行一个回调(onload、 onfocus、 < script > 等等。.)在一个时间(每标签,大概)。William 建议在注册和接收回调之间使用互斥对象进行更改,因此不应该过于直接地理解这个建议,因为您不会想要阻止中间的回调,因为将解锁它的回调将在当前回调后被阻止!(哇,讨论线程的英语糟透了。)在这种情况下,如果设置了标志,您可能希望执行类似于重新分派当前事件的操作,无论是字面上的还是使用 setTimeout ()之类的方法。

如果您使用不同的 JS 嵌入,并且同时执行多个线程,那么可能会有些冒险,但是由于 JS 可以如此轻松地使用回调,并且在属性访问上锁定对象,显式锁定几乎没有必要。然而,如果为使用多线程的通用代码(如游戏脚本)设计的嵌入也没有提供一些显式的锁定原语,我会感到惊讶。

对不起,墙上的文字!

这个问题的答案虽然在给出的时候是正确的,但是有点过时了。如果查看不使用 webworker 的客户端 javascript 应用程序仍然是正确的。

关于网络工作者的文章:
在 javascript 中使用 webworker 进行多线程处理
网络工作者上的 Mozilla

这清楚地表明通过 web-worker 实现的 javascript 具有多线程能力。关于这个问题,javascript 中需要互斥对象吗?我不确定。但是这篇堆栈溢出的帖子似乎很有意义:
Mutual Exclusion for N Asynchronous Threads

正如@william 指出的,

如果您的代码在需要 值,不要在触发异步事件时与触发异步事件时之间更改 当回调被调用的时候。

这可以进一步推广——如果您的代码在异步请求解决之前需要对资源进行独占控制,那么您可能需要一个互斥锁。

一个简单的例子是,您有一个按钮,它会发出一个 ajax 调用来在后端创建一条记录。您可能需要一些代码来保护您免受快乐用户的点击,从而创建多条记录的影响。有许多方法可以解决这个问题(例如,禁用按钮,在 ajax 成功时启用)。您还可以使用一个简单的锁:

var save_lock = false;
$('#save_button').click(function(){
if(!save_lock){
//lock
save_lock=true;
$.ajax({
success:function()
//unlock
save_lock = false;
}
});
}
}

我不确定这是否是最好的方法,我很想看看其他人是如何用 javascript 处理互斥锁的,但据我所知,这是一个简单的互斥对象,而且很方便。

是的,当访问在选项卡/窗口之间共享的资源(如 本地存储)时,可能需要在 Javascript 中使用互斥对象。

例如,如果用户打开了两个选项卡,下面这样的简单代码就不安全:

function appendToList(item) {
var list = localStorage["myKey"];
if (list) {
list += "," + item;
}
else {
list = item;
}
localStorage["myKey"] = list;
}

在 localStorage 项“ got”和“ set”之间,可能有另一个选项卡修改了该值。这通常不太可能,但是有可能——你需要自己判断在你的特殊情况下与任何争论相关的可能性和风险。

See the following articles for a more detail: