简单的JavaScript互斥锁

简单的JavaScript互斥锁

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

  View Code

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

锁与解锁

等待队列

执行方法

以上锁的用法:

//定义锁的名称var lock = 'scrollTop()';//使用锁$.indream.async.lock(lock, function () { var scrollTop = $(window).scrollTop(); var timer; var fullTime = 100; for (timer = 0; timer

关于这次所的实现,简单说明下。

-自旋锁还是信号量

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

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

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

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

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

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

把代码段(回调的action)推入等待队列

判断当前锁是否被持有,如果被持有则等待释放,否则获取该锁,执行回调

当锁被释放,则在等待队列中shift出下一个回调,将锁传递给它并执行

-自动释放还是手动释放

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

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

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

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

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

绿色通道:好文要顶关注我收藏该文与我联系

Indream Luo

关注 - 1

粉丝 - 27

+加关注

1

0

(请您对文章做出评价)

上一篇:为jQuery添加Webkit的触摸方法支持

posted @ 2014-02-02 16:10 Indream Luo 阅读(624) 评论(10) 编辑 收藏

评论列表

#1楼 2014-02-02 16:59 BarretLee

如果没有使用worker,不会同时有两个程序操作资源,互斥的使用场景并不多。

你文中所说'JavaScript双线程的原理'是在哪里看到的?单线程吧?

支持(1)反对(0)

#2楼[楼主] 2014-02-02 17:52 Luo Indream

@BarretLee

引用如果没有使用worker,不会同时有两个程序操作资源,互斥的使用场景并不多。

你文中所说'JavaScript双线程的原理'是在哪里看到的?单线程吧?

呵呵,“单线程”已修正,顺便找到了后面俩错别字。多谢了。

我之前在两种场景常使用锁,一种是有比较多的Ajax请求,另一种是比较多的UI动画交互。一个是需要等到数据才能执行很多东西,而不同的Http请求速度不一致导致很多麻烦,需要用锁;另一个是交互的时候需要等一些动画播放完毕才能执行其他的东西。如果两个场景同时出现,会使用大量的锁,比如我做的IM。

支持(0)反对(0)

#3楼 2014-02-02 17:58 看门的判官

锁就是给数据加个开关来控制访问权

支持(0)反对(0)

#4楼[楼主] 2014-02-02 18:05 Luo Indream

@看门的判官

哈哈,对的,要文艺点说就是“让程序按照需要的顺序使用数据。”

我觉得是源自于一种权限模拟的需求。因为内存是共有的,但抽象后的业务对象不是,需要模拟出这种效果。

支持(0)反对(0)

#5楼 2014-02-02 21:44 BarretLee

比较多的 ajax 请求,你指的是两个 ajax 队列,一个读一个写? 比较多的 UI 动画交互,你指的是,多次 js 操作然后需要立即渲染? 这些问题根本没必要使用互斥锁来完成,单线程阻塞运行是 js 最大的一个特点,利用 js 的异步特性就可以处理上述的几个问题。

可以看看我上次写的JavaScript异步编程原理

需要使用互斥锁的场景,我也碰到过,一种是多 worker 读写数据,一种是多页面读写本地储存或者 cookie,这些场景都是十分少见的。

支持(0)反对(0)

#6楼[楼主] 2014-02-02 22:55 Luo Indream

@BarretLee

引用比较多的 ajax 请求,你指的是两个 ajax 队列,一个读一个写? 比较多的 UI 动画交互,你指的是,多次 js 操作然后需要立即渲染? 这些问题根本没必要使用互斥锁来完成,单线程阻塞运行是 js 最大的一个特点,利用 js 的异步特性就可以处理上述的几个问题。

可以看看我上次写的JavaScript异步编程原理

需要使用互斥锁的场景,我也碰到过,一种是多 worker 读写数据,一种是多页面读写本地储存或者 cookie,这些场景都是十分少见的。

是的,我用的场景差不多。

一个实例是我做IM的时候,用大量的Ajax去读数据,但是又要减少服务器压力,所以会用到比较多的缓存。这时候理想的处理就是:判断是否有缓存->没有则去读->读到后缓存起来。不过实际情况是,比如打开一个会话,有一个人发了10条记录,那么就需要读取他的个人信息10次。为了防止并发读取浪费资源,那么负责读取的程序就应该互斥。

还有一个是在UI交互比较多的情况下会发生。在某个动画(向左切换)播放完之前触发了某个动画(向右切换),而原有动画并不是阻塞连续(组合动画)的,很容易出现先解决了后来者。这样出现的原因就是机制上不阻塞,但是我们需要它阻塞,所以就要用到锁了。

不过很多情况可以从设计到方案上进行替换解决,也可能会有更优的方案。一般需要锁的情况都是与浏览器内核其他线程交互相关的情况,比如UI渲染、计时器、AJAX请求、资源加载之类的。要一般单执行JS自身任务的情况下,需要锁的并不多,原有的回调、订阅机制就很够用了。

P.S.

你的那片博客内容挺全,学习了。本身不是做前端的,所以要多多向前端牛们学习下。

支持(0)反对(0)

#7楼 2014-02-03 10:10 mr.cui

什么情况下需要这个东西呢?

感觉好像是程序员的程序想法,也就是刚开始是为了解决一个问题要抽象到一个通用的方法,做着做着,目的结果逐渐偏离问题本质了,最后做出来的东西要么做复杂了要么不实用。

支持(0)反对(0)

#8楼 2014-02-03 10:16 winpzs

没必要吧? javascript本来就只是单线程, AJAX、jQuery动画用jQuery的Deferred就完美解决了.

支持(1)反对(0)

#9楼 2014-02-03 11:10 麦舒

@winpzs

引用没必要吧? javascript本来就只是单线程, AJAX、jQuery动画用jQuery的Deferred就完美解决了.

好象是这么回事

简单的JavaScript互斥锁

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

  View Code

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

锁与解锁

等待队列

执行方法

以上锁的用法:

//定义锁的名称var lock = 'scrollTop()';//使用锁$.indream.async.lock(lock, function () { var scrollTop = $(window).scrollTop(); var timer; var fullTime = 100; for (timer = 0; timer

关于这次所的实现,简单说明下。

-自旋锁还是信号量

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

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

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

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

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

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

把代码段(回调的action)推入等待队列

判断当前锁是否被持有,如果被持有则等待释放,否则获取该锁,执行回调

当锁被释放,则在等待队列中shift出下一个回调,将锁传递给它并执行

-自动释放还是手动释放

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

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

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

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

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

绿色通道:好文要顶关注我收藏该文与我联系

Indream Luo

关注 - 1

粉丝 - 27

+加关注

1

0

(请您对文章做出评价)

上一篇:为jQuery添加Webkit的触摸方法支持

posted @ 2014-02-02 16:10 Indream Luo 阅读(624) 评论(10) 编辑 收藏

评论列表

#1楼 2014-02-02 16:59 BarretLee

如果没有使用worker,不会同时有两个程序操作资源,互斥的使用场景并不多。

你文中所说'JavaScript双线程的原理'是在哪里看到的?单线程吧?

支持(1)反对(0)

#2楼[楼主] 2014-02-02 17:52 Luo Indream

@BarretLee

引用如果没有使用worker,不会同时有两个程序操作资源,互斥的使用场景并不多。

你文中所说'JavaScript双线程的原理'是在哪里看到的?单线程吧?

呵呵,“单线程”已修正,顺便找到了后面俩错别字。多谢了。

我之前在两种场景常使用锁,一种是有比较多的Ajax请求,另一种是比较多的UI动画交互。一个是需要等到数据才能执行很多东西,而不同的Http请求速度不一致导致很多麻烦,需要用锁;另一个是交互的时候需要等一些动画播放完毕才能执行其他的东西。如果两个场景同时出现,会使用大量的锁,比如我做的IM。

支持(0)反对(0)

#3楼 2014-02-02 17:58 看门的判官

锁就是给数据加个开关来控制访问权

支持(0)反对(0)

#4楼[楼主] 2014-02-02 18:05 Luo Indream

@看门的判官

哈哈,对的,要文艺点说就是“让程序按照需要的顺序使用数据。”

我觉得是源自于一种权限模拟的需求。因为内存是共有的,但抽象后的业务对象不是,需要模拟出这种效果。

支持(0)反对(0)

#5楼 2014-02-02 21:44 BarretLee

比较多的 ajax 请求,你指的是两个 ajax 队列,一个读一个写? 比较多的 UI 动画交互,你指的是,多次 js 操作然后需要立即渲染? 这些问题根本没必要使用互斥锁来完成,单线程阻塞运行是 js 最大的一个特点,利用 js 的异步特性就可以处理上述的几个问题。

可以看看我上次写的JavaScript异步编程原理

需要使用互斥锁的场景,我也碰到过,一种是多 worker 读写数据,一种是多页面读写本地储存或者 cookie,这些场景都是十分少见的。

支持(0)反对(0)

#6楼[楼主] 2014-02-02 22:55 Luo Indream

@BarretLee

引用比较多的 ajax 请求,你指的是两个 ajax 队列,一个读一个写? 比较多的 UI 动画交互,你指的是,多次 js 操作然后需要立即渲染? 这些问题根本没必要使用互斥锁来完成,单线程阻塞运行是 js 最大的一个特点,利用 js 的异步特性就可以处理上述的几个问题。

可以看看我上次写的JavaScript异步编程原理

需要使用互斥锁的场景,我也碰到过,一种是多 worker 读写数据,一种是多页面读写本地储存或者 cookie,这些场景都是十分少见的。

是的,我用的场景差不多。

一个实例是我做IM的时候,用大量的Ajax去读数据,但是又要减少服务器压力,所以会用到比较多的缓存。这时候理想的处理就是:判断是否有缓存->没有则去读->读到后缓存起来。不过实际情况是,比如打开一个会话,有一个人发了10条记录,那么就需要读取他的个人信息10次。为了防止并发读取浪费资源,那么负责读取的程序就应该互斥。

还有一个是在UI交互比较多的情况下会发生。在某个动画(向左切换)播放完之前触发了某个动画(向右切换),而原有动画并不是阻塞连续(组合动画)的,很容易出现先解决了后来者。这样出现的原因就是机制上不阻塞,但是我们需要它阻塞,所以就要用到锁了。

不过很多情况可以从设计到方案上进行替换解决,也可能会有更优的方案。一般需要锁的情况都是与浏览器内核其他线程交互相关的情况,比如UI渲染、计时器、AJAX请求、资源加载之类的。要一般单执行JS自身任务的情况下,需要锁的并不多,原有的回调、订阅机制就很够用了。

P.S.

你的那片博客内容挺全,学习了。本身不是做前端的,所以要多多向前端牛们学习下。

支持(0)反对(0)

#7楼 2014-02-03 10:10 mr.cui

什么情况下需要这个东西呢?

感觉好像是程序员的程序想法,也就是刚开始是为了解决一个问题要抽象到一个通用的方法,做着做着,目的结果逐渐偏离问题本质了,最后做出来的东西要么做复杂了要么不实用。

支持(0)反对(0)

#8楼 2014-02-03 10:16 winpzs

没必要吧? javascript本来就只是单线程, AJAX、jQuery动画用jQuery的Deferred就完美解决了.

支持(1)反对(0)

#9楼 2014-02-03 11:10 麦舒

@winpzs

引用没必要吧? javascript本来就只是单线程, AJAX、jQuery动画用jQuery的Deferred就完美解决了.

好象是这么回事


相关文章

  • Javascript的10个设计缺陷
  • 一.为什么Javascript 有设计缺陷? 这里有三个客观原因,导致Javascript 的设计不够完善. 1. 设计阶段 过于仓促 Javascript 的设计,其实只用了十天.而且,设计师是为了向公司交差,本人并不愿意这样设计(参见& ...查看


  • 网页设计与制作课程标准
  • <网页设计与制作>课程标准 一.概述 (一)课程性质(课程性质和价值) 本课程是五年制高职计算机网络技术专业的一门主干专业课程.通过本课程的学习,要求学生掌握网页设计的基本概念,学会使用常用的网页设计工具和常用脚本语言,能够设计 ...查看


  • 前端需要掌握的11项技能
  • 导读: 你也许会觉得前端开发是一个很简单的工作,对呀,你就是刚刚从网页设计转型过来的.但当你深入其中时,一定会发现好像前端开发不是那么简单,光网站性能优化.响应式.框架就让你焦头烂额.确实,做前端开发就是先易后难,想成为一个优秀的前端开发, ...查看


  • 如何提高网页页面的响应速度
  • 如何提高网页页面响应速度 访问速度缓慢的互联网已经成为过去,但页面能瞬时呈现也只是未来才会发生的事情. Christian heilmann的一些技巧,现在就可以令你的网站访问起来更为流畅. 页面首次访问时的延时是网站和Web应用设计中遇到 ...查看


  • 进程同步的教学方法探讨
  • 计算机时代2009年第9期 ・ 7l ・ 进程同步的教学方法探讨 白秀玲.宋晓莉,邱涌,张营.张孝国.杨春蕾(河南科技大学电子信息工程学院,河南洛阳47l003) 摘要:在操作系统课程的教学中,进程同步是其中一个重点,也是难点.进程概念较抽 ...查看


  • 43款可视化工具介绍及软件地址
  • 点击上"海量大数据实践"可以订阅哦!明天的研习社活动中,永洪科技渠道总监王桐将带来用数据可视化的精彩案例,那么我们先看看当前热用的43款可视化工具,包括Arbor.Chroma.js.D3.js.Google Chart ...查看


  • 用函数式编程技术编写优美的 JavaScript
  • 文档选项 将此页作为电子邮件发送 未显示需要 JavaScript 的文档选项 最新推荐 Java 应用开发源动力 - 下载免费软件,快速启动开发 级别: 初级 Shantanu Bhattacharya (shantanu@justawo ...查看


  • 客户端学习总结
  •     前面几个星期,我们学习了客户端的知识,其中主要有3个部分:xhtml,css,js.通过学习,我对客户端网页编程有了一个初步的了解,xhtml主要是页面内容的一个体现,是静态网页设计的基础,css用来控制页面的布局和网页的表现形式, ...查看


  • json的定义.标准格式及json字符串检验
  • 现在越来越多的项目和开发插件等默认都会支持和使用json数据格式,作为数据保持.传输的一种方式. 说是其中一种,就标示还有好多其他格式.比如:最多是xml.webservice的标准数据格式. 不过由于json是JavaScript 对象表 ...查看


热门内容