首頁  >  文章  >  web前端  >  簡單的JavaScript互斥鎖分享_javascript技巧

簡單的JavaScript互斥鎖分享_javascript技巧

WBOY
WBOY原創
2016-05-16 17:01:412013瀏覽

去年有幾個專案需要使用JavaScript互斥鎖,所以寫了幾個類似的,這是其中一個:

複製程式碼 程式碼如下:

//Published by Indream Luo
//Contact: indreamluo@qq.com
//Version: Chinese 1.0.0

!function ($) {
    window.indream = window.indream || {};
    $.indream = indream;

    indream.async = {
        //
        //鎖定
   🎜>        //
        lock : function (lock, action) {
            $.indream.async.waitings[lock] = $.indream.async.waitings[lock] .push(action);
            //若鎖定使用,則目前action阻塞此鎖定
                   $.indream .async.lockStatus[lock] = true;
               if (arguments.length > 2) {                    for (var i = 3; i                         args = ', arguments 🎜>                    eval('$.indream.async.action.call(action, ' args ')');
                } else {
                    $.indream.async.action.call(action);
                }
            }
        },
        //
        //解鎖
        //lock : 鎖的編號
        //
        releaseLock: function (lock) {
              //若等待佇列有對象,則執行等待隊列,否則解鎖
            if ($.indream.async.waitings[lock].length) {
                  } else {
                $.indream.async.lockStatus[lock] = false;
          //
        //鎖定的狀態
        //
       
        //
        //且有完成事件完成
        //lock:作用   wait: function (lock , action) {
            $.indream.async.waitings[code] = $.indream.async.waitings[code] || [];
   . );
        },
        //
        //等待序列
        //
         //資料快取
        //
        action: {
            //
            //監控與回復相關的相關方法                //
                             listen: function (actionName , callback) {
                    var list = $.indream.async.action.callback. ] = list[actionName] || [];
                    list[actionName].push(callback );
                },
                              //
                  var list = $.indream.async.action.callback .list;
                   if (list[actionName] && list[actionName].leng    (var i in list[actionName]) {
                         地actionName][i], args);
                        }                //                list: []
            },
            //
            //使用中使用與參數是否有選擇適當的執行方式       call: function (action) {
                if (action) {
if (arguments.length > 1) {
                              for (var i = 2; i                              ' i ']';
                        }
     ');
                    } else {
                         }
               
        }
    }
}(window.jQuery);



一個互斥鎖的幾個元素是:

•鎖與解鎖

•等待隊列•執行方法

以上鎖的用法:




複製程式碼

程式碼如下://定義鎖定的名稱var 時'scrollTop()';//使用鎖
$.indream.async.lock(lock, function () {
    var scrollTop = $(window).scrollTop();
var ti  ;
    var fullTime = 100;
    for (timer = 0; timer       / fullTime) ');', timer);
    }
    //釋放鎖
    setTimeout('$.indream.async.releaseLock("' lock '");', full); >});



關於這次所的實現,簡單說明下。

-自旋鎖還是信號量
JavaScript本身沒有鎖的功能,所以做的鎖都是在高層實現的。
依據JavaScript單執行緒的原理,JS的執行緒資源十分有限,非常不適合使用自旋鎖,所以選擇了使用信號量。

自旋鎖實現起來的樣子大致上是這樣的,當然do while更多用了:


複製程式碼

程式碼如下:while(true) {while(true) {

while(true) {
> ...
}

這樣必然需要佔滿執行緒資源,可惜JS只有一條執行緒可以用來執行,所以這樣做十分不適用。當然,有需要可以選擇setInterval和clearInterval的組合去實現,效果也會不錯。

這裡選用了信號量的方式,原理也簡單,就如程式碼那麼短。工作的執行順序大致是:

•把程式碼段(回呼的action)推入等待佇列
•判斷目前鎖是否被持有,如果被持有則等待釋放,否則取得該鎖,執行回呼
•當鎖被釋放,則在等待佇列中shift出下一個回調,將鎖定傳遞給它並執行
 

-自動釋放還是手動釋放
看起來最舒服的方式當然是鎖住之後噹噹前程式執行完就自動釋放,不過這樣並不容易,因為有更多的情況需要自訂釋放場景。

本身使用鎖定的就是在非同步中的方法,所以各種通常也會出現其他非同步內容,例如AJAX、jQuery動畫。這時候,自動釋放就不符合需求了,因為實際上真正的「執行完畢」是在它內部的非同步回調完成後,也就是基本上只有開發人員自己能把握,所以這裡選擇了手釋放。

不過還是有缺陷的,就是重複釋放。

可以看到所有的鎖的物件都是公有的,或者應該說JS所有物件都是公有的,除非使局部變數在存取層級上進行隔離。不過這裡「鎖」本身就是個公共資源,所以沒辦法處理。

這裡可以做的優化應該是像setInterval和clearInterval的那樣,以公共的鎖名稱進行加鎖,以私有的鎖ID進行解鎖,就可以防止重複釋放了。不過上面這段老程式碼中沒有,估計很快就會用到的了。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn