我正在尝试根据我的需要实现一个交叉表互斥锁。我在这里找到了一个实现。这似乎很有希望。基本上,它实现了Leslie Lamport 的算法,需要原子读/写来创建互斥锁。
然而,它依赖于 localStorage 提供原子读/写。这适用于除 Chrome 之外的大多数浏览器。
所以我的问题是,我可以改用 cookie 读/写吗?所有主流浏览器(IE、Chrome、Safari、Firefox)中的 cookie 读/写都是原子的吗?
我正在尝试根据我的需要实现一个交叉表互斥锁。我在这里找到了一个实现。这似乎很有希望。基本上,它实现了Leslie Lamport 的算法,需要原子读/写来创建互斥锁。
然而,它依赖于 localStorage 提供原子读/写。这适用于除 Chrome 之外的大多数浏览器。
所以我的问题是,我可以改用 cookie 读/写吗?所有主流浏览器(IE、Chrome、Safari、Firefox)中的 cookie 读/写都是原子的吗?
既不 cookie,也不localStorage
提供原子事务。
我想你可能误解了那篇博文,它并没有说他的实现在 Chrome 中不起作用,它不依赖于localStorage
提供 atomic read/writes。他说Chrome 中的正常 localStorage
访问更加不稳定。我假设这与 Chrome 为每个选项卡使用单独的进程这一事实有关,而大多数其他浏览器倾向于对所有选项卡使用单个进程。他的代码实现了一个锁定系统,在该系统之上localStorage
应该可以防止事情被覆盖。
另一种解决方案是使用IndexedDB。IndexedDB确实提供原子事务。作为一个新标准,它不受localStorage
.
不会。即使浏览器可能在 cookie 上实现了读取和写入锁定,它也不会保护您免受读取和后续写入之间发生的更改的影响。通过查看cookie 的 javascript API很容易看出这一点,那里没有互斥锁功能......
我今天使用 localStorage 遇到了这个并发问题(两年后..)
场景:浏览器的多个选项卡(例如 Chrome)具有相同的脚本代码,它们基本上同时执行(由例如 SignalR 调用)。代码读取和写入 localStorage。由于选项卡在不同的进程中运行但共同访问共享的本地存储,因此读取和写入会导致未定义的结果,因为这里缺少锁定机制。就我而言,我想确保只有一个选项卡实际上与本地存储一起使用,而不是所有选项卡..
我尝试了上面问题中提到的 Benjamin Dumke-von der Ehe 的锁定机制,但得到了不希望的结果。所以我决定推出自己的实验代码:
本地存储锁:
Object.getPrototypeOf(localStorage).lockRndId = new Date().getTime() + '.' + Math.random();
Object.getPrototypeOf(localStorage).lock = function (lockName, maxHold, callback) {
var that = this;
var value = this.getItem(lockName);
var start = new Date().getTime();
var wait = setInterval(function() {
if ((value == null) || (parseInt(value.split('_')[1]) + maxHold < start)) {
that.setItem(lockName, that.lockRndId + '_' + start);
setTimeout(function () {
if (that.getItem(lockName) == (that.lockRndId + '_' + start)) {
clearInterval(wait);
try { callback(); }
catch (e) { throw 'exeption in user callback'; }
finally { localStorage.removeItem(lockName); }
}
}, 100);
}
}, 200);
};
用法:
localStorage.lock( lockName , maxHold , callback );
例如: “只在一个标签中播放声音”
//var msgSound = new Audio('/sounds/message.mp3');
localStorage.lock('lock1', 5000, function(){
// only one of the tabs / browser processes gets here at a time
console.log('lock aquired:' + new Date().getTime());
// work here with local storage using getItem, setItem
// e.g. only one of the tabs is supposed to play a sound and only if none played it within 3 seconds
var tm = new Date().getTime();
if ((localStorage.lastMsgBeep == null)||(localStorage.lastMsgBeep <tm-3000)) {
localStorage.lastMsgBeep = tm;
//msgSound.play();
console.log('beep');
}
});