去年有幾個專案需要使用JavaScript互斥鎖,所以寫了幾個類似的,這是其中一個:
!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);
一個互斥鎖的幾個元素是:
•鎖與解鎖
以上鎖的用法:
自旋鎖實現起來的樣子大致上是這樣的,當然do while更多用了:
複製程式碼
這樣必然需要佔滿執行緒資源,可惜JS只有一條執行緒可以用來執行,所以這樣做十分不適用。當然,有需要可以選擇setInterval和clearInterval的組合去實現,效果也會不錯。
這裡選用了信號量的方式,原理也簡單,就如程式碼那麼短。工作的執行順序大致是:
•把程式碼段(回呼的action)推入等待佇列
•判斷目前鎖是否被持有,如果被持有則等待釋放,否則取得該鎖,執行回呼
•當鎖被釋放,則在等待佇列中shift出下一個回調,將鎖定傳遞給它並執行
-自動釋放還是手動釋放
看起來最舒服的方式當然是鎖住之後噹噹前程式執行完就自動釋放,不過這樣並不容易,因為有更多的情況需要自訂釋放場景。
本身使用鎖定的就是在非同步中的方法,所以各種通常也會出現其他非同步內容,例如AJAX、jQuery動畫。這時候,自動釋放就不符合需求了,因為實際上真正的「執行完畢」是在它內部的非同步回調完成後,也就是基本上只有開發人員自己能把握,所以這裡選擇了手釋放。
不過還是有缺陷的,就是重複釋放。
可以看到所有的鎖的物件都是公有的,或者應該說JS所有物件都是公有的,除非使局部變數在存取層級上進行隔離。不過這裡「鎖」本身就是個公共資源,所以沒辦法處理。
這裡可以做的優化應該是像setInterval和clearInterval的那樣,以公共的鎖名稱進行加鎖,以私有的鎖ID進行解鎖,就可以防止重複釋放了。不過上面這段老程式碼中沒有,估計很快就會用到的了。