简单的JavaScript互斥锁分享

 这篇文章主要介绍了简单的JavaScript互斥锁的相关资料,需要的朋友可以参考下

去年有几个项目需要使用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进行解锁,就可以防止重复释放了。不过上面这段老代码中没有,估计很快就会用到的了。
 

时间: 2024-08-03 03:08:03

简单的JavaScript互斥锁分享的相关文章

Linux下一个简单的多线程互斥锁的例子

本篇文章是对Linux下一个简单的多线程互斥锁的例子进行了分析介绍,需要的朋友可以参考下   复制代码 代码如下: #include <stdio.h> #include <pthread.h> pthread_mutex_t Device_mutex ; int count=0; void thread_func1() {    while(1)    {        pthread_mutex_lock(&Device_mutex);        printf(&q

一个简单的JavaScript Map实例(分享)_javascript技巧

用js写了一个Map,带遍历功能,请大家点评下啦. //map.js Array.prototype.remove = function(s) { for (var i = 0; i < this.length; i++) { if (s == this[i]) this.splice(i, 1); } } /** * Simple Map * * * var m = new Map(); * m.put('key','value'); * ... * var s = ""; *

浅析Linux下一个简单的多线程互斥锁的例子_unix linux

复制代码 代码如下: #include <stdio.h>#include <pthread.h>pthread_mutex_t Device_mutex ;int count=0;void thread_func1(){   while(1)   {       pthread_mutex_lock(&Device_mutex);       printf("thread1: %d\n",count);       pthread_mutex_unlo

Java互斥锁简单实例_java

本文实例讲述了Java互斥锁.分享给大家供大家参考.具体分析如下: 互斥锁,常常用于多个线程访问独占式资源,比如多个线程同时写一个文件,虽然互斥访问方式不够高效,但是对于一些应用场景却很有意义 //没有互斥锁的情况(可以自己跑跑看运行结果): public class LockDemo { // private static Object lock = new Object(); // static确保只有一把锁 private int i = 0; public void increaseI(

分享一个自己写的简单的javascript分页组件

 这篇文章主要分享一个自己写的简单的javascript分页组件,效果十分不错,代码也很详尽,这里推荐给小伙伴们.     自己写的一个简单的分页组件,主要功能还有实现都在JS中,html页面中只用增加一个放置生成分页的DIV,并给定容器的id. html结构如下:   代码如下: <ul class="pagination" id="pageDIV"> </ul> class="pagination" 给定了分页的样式,

分享一个 Node 进程互斥锁小模块 - lockman

介绍 lockman 是一个用于多进程的「互斥锁」, 类似一些语言中(比如 C#)的 lock 关键字可以用来确保代码块完成运行,而不会被其他进程「影响」.它可以把一段代码定义为「互斥段」(critical section),「互斥段」在一个时刻内只允许一个进程进入执行,而其他进程必须等待. 不同之处,C# 的 lock 关键字作用在「线程间」,lockman 作用在 Node 的进程间. Git Repo: https://github.com/Houfeng/lockman 安装 $ npm

互斥锁和条件变量

为了允许在线程或进程之间共享数据,同步时必须的,互斥锁和条件变量是同步的基本组成部分. 1.互斥锁 互斥锁是用来保护临界区资源,实际上保护的是临界区中被操纵的数据,互斥锁通常用于保护由多个线程或多进程分享的共享数据.一般是一些可供线程间使用的全局变量,来达到线程同步的目的,即保证任何时刻只有一个线程或进程在执行其中的代码.一般加锁的轮廓如下: pthread_mutex_lock() 临界区 pthread_mutex_unlock() 互斥锁API pthread_mutex_lock(pth

介绍一个简单的JavaScript类框架

  这篇文章主要介绍了一个简单的JavaScript类框架,有助于初学者理解JS类的创建与继承,需要的朋友可以参考下 在写work-in-progress JavaScript book一书时,对于javascript继承体系,我花费了相当的时间,并在该过程中研究了各种不同的模拟经典类继承的方案.这些技术方案中,我最为推崇的是base2与Prototype的实现. 从这些方案中,应该能提炼出一个具有其思想内涵的框架,该框架须具有简单.可重用.易于理解并无依赖等特点,其中简单性与可用性是重点.以下

深入理解linux互斥锁(mutex)

                                      深入理解linux互斥锁(mutex)     锁机制,可以说是linux整个系统的精髓所在,linux内核都是围绕着同步在运转.在多进程和多线程编程中,锁起着极其重要的作用.我这里说的是互斥锁,其实是泛指linux中所有的锁机制.我在这里不讲如果创建锁,关于锁的创建,网上代码很多,我在这里就不多说了.我要谈一谈一个让所有刚刚接触锁机制的程序员都很困惑的问题:如何使用以及锁机制在程序中是如何运作的.     为什么要使用