同步同一个Greasemonkey脚本的多个实例

时间:2014-12-06 13:19:08

标签: javascript multithreading greasemonkey

我有一个Greasemonkey用户脚本,可以在任务队列上运行。此队列是一系列序列化的JSON对象,分散在脚本专用首选项空间中,可通过GM_getValueGM_setValueGM_listValues进行访问。

我想让这个脚本同时运行(相同的机器,相同的浏览器,不同的选项卡),同时仍然保持共享队列。我知道Javascript主要运行在一个线程中(Web Workers除外),但我认为在不同的选项卡中打开的页面不是这样,所以它必须同时运行。

在这种情况下,如何正确组织对此类对象的共享访问,以防止竞争条件?竞争条件会出现吗?

1 个答案:

答案 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()广播和维护那些想要获取“互斥”的人的待处理队列,实现一个监视器(因为每个脚本调用都在一个关键部分)。