在Appium1.7.1里集成了一个同步模块async-lock用来支持多会话功能。

只能说就算是以单线程高并发闻名的I/O密集型Nodejs也不得不扩展额外的同步块方法,或者说,在现有的计算机体系结构和配备的操作系统之下,所有的编程语言都无法摒弃同步信息块。

不过想想也是,这个世界原本是处于无序的状态,只是有了人类的干预,才会让一切事情直着走。要是没有同步块,所有的线程(Nodejs底层的异步也是多线程)就会如野草生成一般,力量强大,但不可被控制,而不可被控制恰恰是不能被人类所容忍的。

首先需要明白一点的是,或者说以下内容的前提是,Nodejs碰到异步回调会启动I/O,之后继续往下执行。

以官网的两句代码(https://www.npmjs.com/package/async-lock)为例:

user1和user1操作redis数据库,取同一个键的值乘以2:

User1
lock.acquire('key', function(cb){
// Concurrency safe
redis.get('key', function(err, value){
redis.set('key', value * 2, cb);
});
}, function(err, ret){
});
User2
lock.acquire('key', function(cb){
// Concurrency safe
redis.get('key', function(err, value){
redis.set('key', value * 2, cb);
});
}, function(err, ret){
});

acquire函数的签名如下:

AsyncLock.prototype.acquire = function (key, fn, cb, opts)

key:就是”key”

fn:就是执行的函数

cb:fn函数执行完后的回调函数

opts:配置参数

再看acquire函数的具体实现

对于User1,进入acquire函数执行的是:

这里是个关键:queue是一个字典型,一开始key为空,queue[‘key’]已经被赋值空数组了,执行exec(true)函数。

exec函数:

if else判断需要返回的是Promise,还是以函数回调的方式结束

User1、User2的例子是函数回调方式,所以进入if条件执行。

cb是fn(cb)传过来的,在执行完fn()函数后,就会调用cb:

这里是重点,在调用fn之前,都是CPU在执行,现在执行fn函数,会有回调,这个时候异步I/O启动,CPU继续往下执行,这里的CPU往下执行不是进入fn函数体,而是执行User2的代码,即开始执行:

还是进入acquire函数,这个时候走的是另一个分支:

把exec函数存进一个数组,然后User2就执行完了。CPU继续往下执行User2之后的代码。

假如在某个时刻,User1的异步执行到了cb函数,即红框内的函数:

会调用done函数,其中的关键如下:

可以看到,User2被移出,并且执行其中的exec函数,这样就能保证User2的异步代码在User1之后执行。

总结起来,是以一个中间共有的队列,存放异步函数,在上一个操作完临界资源后,再从队列里shift出来执行异步函数,以达到同步的目的。

async-lock模块理解的更多相关文章

  1. C# async 和 await 理解

    C# async 和 await 理解 先假设如下场景: 主函数 Main,循环等待用户输入: 计算函数 Cal,耗时计算大量数据: class Test { static int Main(stri ...

  2. generator 到 async 的简单理解。

    generator 到 async 的简单理解.觉得实现方式很有意思. 1. generator generator 函数返回一个遍历器对象 遍历器对象 每次调用next 方法 返回 有着value ...

  3. async/await 深度理解使用

    在vue中使用 eg async created () { await setTimeout(()=>{ console.log(1) },5000); }, async mounted () ...

  4. 万向节锁(Gimbal Lock)的理解

    [TOC] 结论 我直接抛出结论: Gimbal Lock 产生的原因不是欧拉角也不是旋转顺序,而是我們的思维方式和程序的执行逻辑没有对应,也就是说是我们的观念导致这个情况的发生. 他人解释 首先我们 ...

  5. await和async更多的理解

    最近有不少网友提起await和async,呵呵,C# 5引进的语法糖. 这个语法糖还真不好吃,能绕倒一堆初学的朋友,在网上也有很多网友关于这块知识点的争论,有对有错,今天在这里把这个误区好好讲讲. 在 ...

  6. async和await理解代码

    <1>:Async和Await的理解1 using System; using System.Collections.Generic; using System.Linq; using S ...

  7. volatile和synchronized与lock的理解

    volatile 特征: a:可见性:一个线程修改了某个共享变量的值,其他线程能够立马得知这个修改. b:禁止特定的处理器重排序. volatile的内存语义: 1.当写一个volatile变量的时候 ...

  8. HTTP模块理解(二)

    这是我在写,用express+ajax+swig来做一个简单的应用的时候,遇到的问题.还是不太理解http模块. 后来在网上看到云栖社区的一篇<Node.js之HTTP请求与响应>,这里做 ...

  9. Node.js的http模块理解

    Node.js标准库提供了http模块,其中封装了一个高效的HTTP服务器和一个简易的HTTP客户端. http.Server是一个基于事件的HTTP服务器,它的核心由C++编写,兼顾高性能和简易性 ...

随机推荐

  1. angularJS1笔记-(20)-模块化加载机制seajs

    SeaJS是一个遵循CMD规范的JavaScript模块加载框架,可以实现JavaScript的模块化开发及加载机制. 与jQuery等JavaScript框架不同,SeaJS不会扩展封装语言特性,而 ...

  2. vue组件讲解(is属性的用法)

    什么是组件? 在说之前我们先搞清楚什么是组件?这样对我们下边的学习是很有帮助的. 组件(Component)是Vue.js最强大的功能之一.组件可以扩展HTML元素,封装可以重复使用的代码.在较高层次 ...

  3. area point sql

    UPDATE aa_info_area t,(SELECT areaId, areacenter,CONCAT('POINT(' ,substring_index(areacenter,',', 1) ...

  4. [转帖]IPV6取代IPV4之路 为何道阻且长?

    IPV6取代IPV4之路 为何道阻且长? 经济学人公众号 IPV6作为IPV4的续命神术,从被提出到现今,逾26年之久.而IPV6在中国更是犹抱琵琶半遮面,千呼万唤难出来,IPV6取代IPV4之路,为 ...

  5. Majority Number III

    Given an array of integers and a number k, the majority number is the number that occursmore than 1/ ...

  6. Flyway学习笔记

    Flyway做为database migration开源工具,功能上像是git.svn这种代码版本控制.google搜索database migration,或者针对性更强些搜索database mi ...

  7. 跳转不同包时候 需要先指定该包的namespace 注意 先跳转 即加上/

  8. BZOJ5286 HNOI/AHOI2018转盘(分块/线段树)

    显然最优走法是先一直停在初始位置然后一次性走完一圈.将序列倍长后,相当于找一个长度为n的区间[l,l+n),使其中ti+l+n-1-i的最大值最小.容易发现ti-i>ti+n-(i+n),所以也 ...

  9. 【转】arm-none-linux-gnueabi-gcc下载

    arm-none-linux-gnueabi-gcc是 Codesourcery 公司(目前已经被Mentor收购)基于GCC推出的的ARM交叉编译工具.可用于交叉编译ARM系统中所有环节的代码,包括 ...

  10. BZOJ2525 [Poi2011]Dynamite 【二分 + 贪心】

    题目链接 BZOJ2525 题解 就是要求所有有炸弹的点到点燃点距离最大值最小 显然二分答案距离\(D\) 然后按深度排序,贪心点燃当前没覆盖的深度最深的点往上第\(D\)层的点 每覆盖一个点要标记其 ...