问题:我想用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) {//delaysetTimeout(() => {if (getItem(this.keyY) !== THREAD_ID) {nextTick(fn) //restartreturn;}//critical sectionresolve();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);
});

有没有可以在JavaScript里可以用的锁?相关推荐

  1. javascript笔记:深入分析javascript里对象的创建(上)续篇

    今天回来一看我的博客居然有这么多人推荐真是开心极了,看来大家对我的研究有了认可,写博客的动力越来越大了,而且我发现写javascript在博客园里比较受欢迎,写java的受众似乎少多了,可能博客园里j ...

  2. JavaScript 里,$ 代表什么?/JQuery是什么语言?/html中用link标签引入css时的中 rel=stylesheet属性?/EL表达式是什么?...

    JavaScript 里,$ 代表什么? 比如说我写一个mouseover事件: $(document).ready(function(){ $("p").mouseover(fu ...

  3. JavaScript里的循环方法:forEach,for-in,for-of

    2019独角兽企业重金招聘Python工程师标准>>> JavaScript诞生已经有20多年了,我们一直使用的用来循环一个数组的方法是这样的: for (var index = 0 ...

  4. javascript里的面向对象

    2019独角兽企业重金招聘Python工程师标准>>> 前言: javascript 项目中原生态的语法用得比较少了,都是基于jQuery开发,但在移动项目中还是比较麻烦的.想整理个 ...

  5. java 动态字符串_Java动态编译执行一串字符串,类似于Javascript里的eval函数

    Javascript里的eval函数能动态执行一串js脚本. 那Java里怎么做到呢. 有两种方法: 一种是使用可以执行js脚本的Java类 ScriptEngineManagerpublic sta ...

  6. java script创建对象_javascript笔记:深入分析javascript里对象的创建

    大家知道在java里面类可以具有静态属性和方法,无需实例化该类的对象,就可以访问这些属性和方法,但是javascript里面是不是只有通过对象初始化方式才会模拟出这样的特点了?其实不然,在编程语言里, ...

  7. 为什么[]==0;JavaScript里什么情况下a==!a为true呢?

    原文链接 JavaScript里什么情况下a==!a为true呢? 答案是当a = []的时候,这是因为JavaScript的类型转换. 我们先来考虑这个问题,console.log([] == fa ...

  8. Javascript里的sleep()方法

    Javascript里的sleep()方法 很多编程语言里都有sleep(),delay()等方法,它能让我们的程序不那么着急的去执行下一步操作,而是延迟.等待一段时间.软件开发中经常会遇到需要这样的 ...

  9. javascript里的document.all用法收集

    javascript里的document.all用法   从IE4开始IE的object model才增加了document.all[],来看看document.all[]的Description: ...

最新文章

  1. Review学生作业管理系统
  2. 开启php的ssl,php怎么开启ssl?开启ssl的方法
  3. 七十三、Vue项目城市详细页的动态路由,Banner布局和公用图片画廊组件拆分
  4. bat产品经理能力模型_产品经理如何构建自己的产品能力模型?
  5. java基础----Date、DateFormat
  6. java实验报告合肥工业大学_合肥工业大学数据结构上机实验代码与实验报告(全)github地址...
  7. 乐高无限无法连接到服务器,乐高无限近期热点问题FQ 新手问题解答
  8. 除了 Tensorflow、PyTorch ,还有哪些深度学习框架值得期待?
  9. 半年全球网络安全入侵事件近千起,超19亿数据受影响
  10. mysql open files
  11. 简述RAID 0,1,5,10区别
  12. 龙格-库塔(Runge-Kutta)方法C++实现
  13. mysql模拟大量数据
  14. devops运维平台汇总
  15. IGRP和EIGRP 详解
  16. 软件工程实验:原型设计
  17. np.meshgrid()函数 以及 三维空间中的坐标位置生成 以及 numpy.repeat()函数介绍
  18. matlab 中实现读取图像上点坐标并在图片上标记点和将坐标显示出来
  19. 网站服务器架构部署方案发展
  20. 通过journalctl查看日志

热门文章

  1. matlab求矩阵中值函数,matlab在一个函数里,如何调用另一个函数里面求得的雅可比矩阵并赋值?...
  2. python2.7装饰器使用_python 函数 装饰器的使用方法
  3. Spring Cloud Feign - 内部实现细节
  4. 容器源码解析之容器全貌(一)
  5. Cannot resolve de.codecentric:spring-boot-admin-starter-server:2.4.0-SNAPSHOT
  6. shell 非_Shell基本操作(一)
  7. all any 或 此运算符后面必须跟_用 ANY、SOME 或 ALL 修改的比较运算符
  8. rust布料怎么弄_布料“难弄”,你需要从这六方面解决!
  9. mysql将大表定时转储_mysql数据库数据定时封装转储
  10. 职业教育计算机课教学反思,关于高职计算机基础课的教学反思.doc