有没有可以在JavaScript里可以用的锁?

问题:我想用localStorage在多个tab下共享数据,但是看了下localStorage里面没有像C++的Mutex一样的锁,那我怎么保证原子的读和写?

答:C++的mutex是使用操作系统的原子性操作实现的,在浏览器环境下没有什么参考的价值。不过,

这篇文章里面,大牛Lamport介绍了利用两块共享区域实现快速锁的算法,如下所示:

假设有两块共享的区域x和y,以及进程的id,以下图的方式进入关键区域

进入关键区域需要的操作至少需要: 写x -> 读y -> 写y -> 读x -> 关键操作 -> 写y。

其中delay必须足够长到使得已经在关键区域内的进程完成关键区域内的操作并退出。

Lamport的文章也证明了这个算法的正确性,可以通过这个链接了解详细的信息。

 

有了这个算法之后,实现一个localStorage上的锁就很简单啦,下面是我的一个简单实现:

const THREAD_ID = `${Math.floor(Math.random() * 1000)} - ${Date.now()}`;

const setItem = localStorage.setItem.bind(localStorage);
const getItem = localStorage.getItem.bind(localStorage);
const removeItem = localStorage.removeItem.bind(localStorage);

const nextTick = fn => setTimeout(fn, 0);

class Mutex {
    constructor (key) {
        this.keyX = `mutex_key_${key}_X`;
        this.keyY = `mutex_key_${key}_Y`;
    }

    lock() {
        return new Promise((resolve, reject) => {
            const fn = () => {
                setItem(this.keyX, THREAD_ID);
                if (!getItem(this.keyY) == null) {
                    nextTick(fn); //restart
                }
                setItem(this.keyY, THREAD_ID);
                if (getItem(this.keyX) !== THREAD_ID) {
                    //delay
                    setTimeout(() => {
                        if (getItem(this.keyY) !== THREAD_ID) {
                            nextTick(fn) //restart
                            return;
                        }
                        //critical section
                        resolve();
                        removeItem(this.keyY);
                    }, 10);
                } else {
                    resolve();
                    removeItem(this.keyY);
                }
            };

            fn();
        });
    }
}

const KEY = 'key';

let mutex = new Mutex(KEY);
mutex.lock().then(() => {
    let value = parseInt(localStorage.getItem(KEY) || 0, 10);
    value += 1;
    localStorage.setItem(KEY, value);
});

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值