去年有几个项目需要使用JavaScript互斥锁,所以写个几个类似的,这是其中一个:

//Published by Indream Luo
//Contact: indreamluo@qq.com
//Version: Chinese 1.0.0!function ($) {window.indream = window.indream || {};$.indream = indream;indream.async = {////锁//lock: 锁的编号//action: 解锁后执行的方法//lock: function (lock, action) {$.indream.async.waitings[lock] = $.indream.async.waitings[lock] || [];$.indream.async.waitings[lock].push(action);//如果该锁未被使用,则当前action阻塞该锁if (!$.indream.async.lockStatus[lock] && action) {$.indream.async.lockStatus[lock] = true;if (arguments.length > 2) {var args = 'arguments[2]';for (var i=3; i<arguments.length; i++) {args += ', arguments[' + i + ']';}eval('$.indream.async.action.call(action, ' + args + ')');} else {$.indream.async.action.call(action);}}},////解锁//lock: 锁的编号//releaseLock: function (lock) {$.indream.async.waitings[lock].shift();//如果等待队列有对象,则执行等待队列,否则解锁if ($.indream.async.waitings[lock].length) {$.indream.async.waitings[lock][0]();} else {$.indream.async.lockStatus[lock] = false;}},////锁的状态//lockStatus: [],////等待事件完成//lock:锁解码,相同的解码将被整合成一个序列,触发时同时触发//wait: function (lock, action) {$.indream.async.waitings[code] = $.indream.async.waitings[code] || [];$.indream.async.waitings[code].push(action);},////等待序列//waitings: [],////数据缓存//action: {////监听和回调的相关方法//callback: {////监听//listen: function (actionname, callback) {var list = $.indream.async.action.callback.list;list[actionName] = list[actionName] || [];list[actionName].push(callback);},////回调//call: function (actionName, args) {var list = $.indream.async.action.callback.list;if (list[actionName] && list[actionName].length) {for (var i in list[actionName]) {$.indream.async.action.call(list[actionName][i], args);}}},////现有的回调列表//list: []},////根据方法是否存在和参数是否存在选择适当的执行方式//call: function (action) {if (action) {if (arguments.length > 1) {var args = 'arguments[1]';for (var i=2; i<arguments.length; i++) {args += ', arguments[' + i + ']';}eval('action(' + args + ')');} else {action();}}}}}
}(window.jQuery);

一个互斥锁的几个元素是:

  • 锁与解锁
  • 等待队列
  • 执行方法

以上锁的用法:

//定义锁的名称
var lock = 'scrollTop()';
//使用锁
$.indream.async.lock(lock, function() {var scrollTop = $(window).scrollTop();var timer;var fullTime = 100;for (timer = 0; timer <= fullTime; timer += 10) {setTimeout('$(window).scrollTop(' + (scrollTop * (fullTime - timer) / fullTime) + ');', timer);}//释放锁setTimeout('$.indream.async.releaseLock("' + lock + '");', fullTime);
});  

关于这次锁的实现,简单说明下.

-自旋锁还是信号量

JavaScript本身没有锁的功能,所以做的锁都是在高层实现的。

依据JavaScript单线程的原理,JS的线程资源十分有限,非常不适合使用自旋锁,所以选择使用信号量。

自旋锁实现起来的样子大致是这样的,当然do while更多用了:

while (true) {//do something...
}

这样必然需要占满线程资源,可惜JS只有一条线程可以用来执行,所以这样做十分不适用。当然有需要可以选择setInterval和clearInterval的组合去实现,效果也会不错。

这里选用了信号量的方式,原理也简单,就如代码那么短。工作的执行顺序大致是:

  • 把代码段(回调的action)推入等待队列
  • 判断当前锁是否被持有,如果被持有则等待释放,否则获取该锁,执行回调
  • 当锁被释放,则在等待队列中shift出下一个回调,将锁传递给它并执行

-自动释放还是手动释放

看起来最舒服的方式当然是锁住之后当当前程序执行完就自动释放,不过这样并不容易,因为有更多的情况需要自定义释放场景。

本身使用锁的就是在异步中的方法,所以各种通常也会出现其他异步内容,比如AJAX、jQuery动画。这个时候,自动释放就不符合需求了,因为实际上真正的“执行完毕”是在它内部的异步回调完成后,也就是基本上只有开发人员自己能把握,所以这里选择了手释放。

不过还是有缺陷的,就是重复释放。

可以看到所有的锁的对象都是公有的,或者应该说JS所有对象都是公有的,除非使局部变量在访问级别上进行隔离。不过这里"锁"本身就是个公共资源,所以没办法处理。

这里可以做的优化应该是像setInterval和clearInterval的那样,以公共的锁名称进行加锁,以私有的锁ID进行解锁,就可以防止重复释放了。不过上面这段老代码中没有,估计很快就会用到的了。

简单的JavaScript互斥锁相关推荐

  1. Linux下多线程编程互斥锁和条件变量的简单使用

    Linux下的多线程遵循POSIX线程接口,称为pthread.编写Linux下的多线程程序,需要使用头文件pthread.h,链接时需要使用库libpthread.a.线程是进程的一个实体,是CPU ...

  2. Qt 互斥锁 QMutex 的简单应用

    Qt 互斥锁 QMutex 的简单应用 在多线程解决问题中,经常会碰到多个线程操作同一片资源,有些时候用信号量的方式去处理,但有的时候需要用到互斥锁. 互斥锁:说白了就是,资源某个时间只能被一个线程使 ...

  3. Multi_thread--Linux下多线程编程互斥锁和条件变量的简单使用

    Linux下的多线程遵循POSIX线程接口,称为pthread.编写Linux下的多线程程序,需要使用头文件pthread.h,链接时需要使用库libpthread.a.线程是进程的一个实体,是CPU ...

  4. Python 多线程总结(2)— 线程锁、线程池、线程数量、互斥锁、死锁、线程同步

    主要介绍使用 threading 模块创建线程的 3 种方式,分别为: 创建 Thread 实例函数 创建 Thread 实例可调用的类对象 使用 Thread 派生子类的方式 多线程是提高效率的一种 ...

  5. java锁(公平锁和非公平锁、可重入锁(又名递归锁)、自旋锁、独占锁(写)/共享锁(读)/互斥锁、读写锁)

    前言 本文对Java的一些锁的概念和实现做个整理,涉及:公平锁和非公平锁.可重入锁(又名递归锁).自旋锁.独占锁(写)/共享锁(读)/互斥锁.读写锁 公平锁和非公平锁 概念 公平锁是指多个线程按照申请 ...

  6. golang:1.并发编程之互斥锁、读写锁详解

    本文转载自junjie,而后稍作修改. 一.互斥锁 互斥锁是传统的并发程序对共享资源进行访问控制的主要手段.它由标准库代码包sync中的Mutex结构体类型代表.sync.Mutex类型(确切地说,是 ...

  7. 信号量,互斥锁,条件变量的联系与区别

    转自:http://blog.chinaunix.net/u3/108685/showart_2127853.html 信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程, ...

  8. 【C++】多线程互斥锁、条件变量

    我们了解互斥量和条件变量之前,我们先来看一下为什么要有互斥量和条件变量这两个东西,了解为什么有这两东西之后,理解起来后面的东西就简单很多了!!! 先来看下面这段简单的代码: int g_num = 0 ...

  9. 【C++】多线程与互斥锁【二】

    文章目录 1. 并发是什么 1.1 并发与并行 1.2 硬件并发与任务切换 1.3 多线程并发与多进程并发 2. 为什么使用并发 2.1 为什么使用并发 2.2 并发和多线程 3. 并发需要注意的问题 ...

最新文章

  1. Nucleus SE RTOS初始化和启动
  2. Python生物信息学⑥绘制热图及火山图
  3. 2.SDL游戏开发:把代码写长一点(一)
  4. nyoj 776 删除元素
  5. 贝特朗奇论 用计算机,关于贝特朗奇论的一点思考
  6. 三菱880彩铅和uni的区别_孟祥雷丨清华美院毕业,彩铅界的“冷军”(附彩铅教程哦!)...
  7. Log4Net 全方位跟踪程序运行
  8. azure备份存储层分类_如何配置Azure SQL数据库长期保留(LTR)备份
  9. opencv 图像旋转_图像数据集增强方式总结和实现【数字图像处理系列四】
  10. STM32的ADC精度提高方法
  11. 解决验证码不显示问题
  12. HTML文本框内容发生变化时引发事件执行
  13. 基于I2C/SPI总线的温湿度采集与OLED显示
  14. 小程序刷新重置当前页面
  15. mac IDEA java 没有javap 安装 The operation couldn’t be completed. Unable to locate a Java Runtime.
  16. crash 和 anr的区别
  17. win10设置md文件默认打开方式
  18. 3. ZCU102 HDMI Demo工程修改【PCIE视频传输】
  19. Linux学习:计算机概论
  20. 投影机检测不到计算机信号,将投影机连接到计算机后,没有信号,如何排除原因?...

热门文章

  1. Spring中@Async用法总结
  2. TLS/SSL 工作原理及握手过程详解
  3. 百度的索引真的比雅虎多么?
  4. Leecode05. 最长回文子串——Leecode大厂热题100道系列
  5. 列出连通集 (25 分)【DFS与BFS模板】
  6. 满分简便代码:1009 说反话 (20分)
  7. GC算法以及垃圾回收器
  8. 安徽计算机应用基础高考试题,安徽省对口高考试题(计算机应用基础部分)
  9. Oracle打开虚拟机闪退,虚拟机上启动Oracle服务为什么自动停止,怎么处理?
  10. oracle数据库开多线程,学习笔记:Oracle表数据导入 DBA常用单线程插入 多线程插入 sql loader三种表数据导入案例...