我有一个Greasemonkey用户脚本,可以在任务队列上运行。此队列是一系列序列化的JSON对象,分散在脚本专用首选项空间中,可通过GM_getValue
,GM_setValue
和GM_listValues
进行访问。
我想让这个脚本同时运行(相同的机器,相同的浏览器,不同的选项卡),同时仍然保持共享队列。我知道Javascript主要运行在一个线程中(Web Workers除外),但我认为在不同的选项卡中打开的页面不是这样,所以它必须同时运行。
在这种情况下,如何正确组织对此类对象的共享访问,以防止竞争条件?竞争条件会出现吗?
答案 0 :(得分:0)
令我惊讶的是,似乎没有竞争条件,因为Javascript在整个浏览器中运行单线程。我用以下用户测试了它:
// ==UserScript==
// @name test-concurrency
// @namespace mw.tools
// @include /^http://localhost//
// @version 1
// @grant GM_getValue
// @grant GM_setValue
// ==/UserScript==
var BLOCK = 1000;
var ATOM = 'foo';
switch (window.location.search) {
case '?inc':
setInterval(function() {
var i;
for (i = 0; i < BLOCK; i++) {
GM_setValue(ATOM, GM_getValue(ATOM, 0) + 1);
}
document.title = '' + GM_getValue(ATOM, 0) + ' || ' + (GM_getValue(ATOM, 0) % BLOCK);
}, 1);
break;
case '?ver':
setInterval(function() {
var v;
var v0;
v0 = GM_getValue(ATOM);
for (i = 0; i < BLOCK; i++) {
v = GM_getValue(ATOM);
if (v != v0) {
document.title = v0 + ' || broken';
alert('BORKEH!!1111oneone');
}
}
document.title = v0;
}, 1);
break;
}
使用较大的BLOCK
值时,无论运行哪个选项卡或窗口违规脚本,浏览器似乎都没有响应。
因此,对于同步脚本,它足以保持一些共享标志告知结构已经使用,并进行随机间隔轮询以使其变为空闲(简单方法,但可以饿死),或使用postWindow()
广播和维护那些想要获取“互斥”的人的待处理队列,实现一个监视器(因为每个脚本调用都在一个关键部分)。