我看过这个链接:在JavaScript中实现互斥。另一方面,我已经读到javascript中没有线程,但这到底是什么意思?
当事件发生时,它们可以在代码中的何处中断?
并且,如果JS中没有线程,是否需要在JS中使用互斥锁?
具体来说,我想知道如何使用功能由所谓的影响setTimeout()
和XmlHttpRequest
的onreadystatechange
对全局访问的变量。
我看过这个链接:在JavaScript中实现互斥。另一方面,我已经读到javascript中没有线程,但这到底是什么意思?
当事件发生时,它们可以在代码中的何处中断?
并且,如果JS中没有线程,是否需要在JS中使用互斥锁?
具体来说,我想知道如何使用功能由所谓的影响setTimeout()
和XmlHttpRequest
的onreadystatechange
对全局访问的变量。
Answers:
Javascript被定义为可重入语言,这意味着没有线程暴露给用户,实现中可能会有线程。像setTimeout()
异步回调之类的函数需要等待脚本引擎休眠后才能运行。
这意味着事件中发生的所有事情都必须先完成,然后才能处理下一个事件。
话虽如此,如果您的代码执行了某些操作,希望在触发异步事件和调用回调之间不更改其值,则可能需要使用互斥锁。
例如,如果您有一个数据结构,在其中单击一个按钮,然后发送一个XmlHttpRequest来调用回调,则该XmlHttpRequest以破坏性的方式更改数据结构,而在事件发生之间,您有另一个按钮直接更改相同的数据结构。触发后,执行回调时,用户可能在回调之前单击并更新了数据结构,这可能会丢失值。
尽管您可以创建这样的竞争条件,但是很容易在代码中避免这种情况,因为每个函数都是原子的。实际上,这将需要大量工作并需要一些奇怪的编码模式才能创建竞争条件。
这个问题的答案虽然在给出时是正确的,但有些过时了。而且,如果查看不使用webworkers的客户端javascript应用程序,则仍然正确。
文章对webworkers:
使用JavaScript中多线程webworkers
的Mozilla上webworkers
这清楚地表明,通过网络工作者的javascript具有多线程功能。关于这个问题,JavaScript是否需要互斥体?我不确定。但是,这个stackoverflow帖子似乎很相关:
N个异步线程的互斥
正如@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中的互斥,但据我所知,这是一个简单的互斥体,非常方便。
while
with setTimeout
或setInterval
with clearInterval
,以便您具有重试和超时逻辑。保留原样意味着您将绕过已锁定的代码。互斥锁和共享对象的外部处理与实现本身一样重要。
是的,访问选项卡/窗口之间共享的资源(例如localStorage)时,JavaScript中可能需要互斥锁。
例如,如果用户打开了两个选项卡,则如下所示的简单代码是不安全的:
function appendToList(item) {
var list = localStorage["myKey"];
if (list) {
list += "," + item;
}
else {
list = item;
}
localStorage["myKey"] = list;
}
在localStorage项目为“ get”和“ set”之间,另一个选项卡可能已修改了该值。通常不太可能,但有可能-您需要自己判断与您的特定情况下任何竞争相关的可能性和风险。
有关更多详细信息,请参见以下文章:
JavaScript是一种语言,可以根据需要使用多线程,但是javascript引擎的浏览器嵌入一次只能运行一次回调(onload,onfocus,<script>等...)。威廉(William)建议使用Mutex在注册和接收回调之间进行更改的建议不应该从字面上理解,因为您不想阻止介入的回调,因为用于解锁该回调的回调将被阻塞在当前回调之后!(哇,英语在谈论线程方面很烂。)在这种情况下,如果设置了一个标志,则可能要沿字面意义或使用setTimeout()之类的方法重新分配当前事件。
如果您使用的是JS的不同嵌入,并且一次执行多个线程,则可能会更加麻烦,但是由于JS可以轻松使用回调并在属性访问中锁定对象的方式,显式锁定几乎没有必要。但是,如果为使用多线程的通用代码(例如游戏脚本)设计的嵌入也没有给出一些明确的锁定原语,我会感到惊讶。
抱歉!