概念:并发并行、同步异步(包括事件循环)、阻塞非阻塞、锁

一. 并发并行

并发:系统具有同一时间段内处理多个任务的能力。

并行:系统具有在同一时刻处理多个任务的能力。

二. 同步 异步 阻塞 非阻塞

1. 进程间的通信层面

进程间的通信时通过 send() 和 receive() 两种基本操作完成的。具体如何实现这两种基础操作,存在着不同的设计。

消息的传递有可能是阻塞的非阻塞的 -- 也被称为同步异步的

1. 阻塞式发送(blocking send). 发送方进程会被一直阻塞, 直到消息被接受方进程收到。

2. 非阻塞式发送(nonblocking send)。 发送方进程调用 send() 后, 立即就可以其他操作。

3. 阻塞式接收(blocking receive) 接收方调用 receive() 后一直阻塞, 直到消息到达可用。

4. 非阻塞式接受(nonblocking receive) 接收方调用 receive() 函数后, 要么得到一个有效的结果, 要么得到一个空值, 即不会被阻塞。

总结:也就是说, 从进程级通信的维度讨论时, 阻塞和同步(非阻塞和异步)就是一对同义词, 且需要针对发送方和接收方作区分对待。

2. 在 IO 系统调用层面( IO system call )层面

原文链接:https://blog.csdn.net/historyasamirror/article/details/5778378

作者的理论描述和比喻都生动形象。

这里为了方便自己快速回顾,在自认为理解作者原意的基础上,做了所谓的提炼,但是显然是有理解不完全或者错误的地方,希望以后自己看到或者过客看到能指正。

如原文作者所述,这里讨论的背景是Linux环境下的network IO。

总览

进程通信层面, 阻塞/非阻塞, 同步/异步基本是同义词, 但是需要注意区分讨论的对象是发送方还是接收方。

主要差别在真实IO层面。所谓真实,是因为我们常说的 阻塞/非阻塞/同步/异步IO,其实更具体应该分为两个阶段,如下:

当发起一个IO请求的时候,会经历两个阶段:

1. 等待数据准备

2. 数据准备好后将数据从kernel(内核)拷贝到进程中

所谓的真实的IO层面指的是数据从内核态拷贝到用户态。

阻塞和非阻塞

区别在于**准备数据阶段**(第一阶段)会不会将进程阻塞。

阻塞IO

发起请求后,在这两个阶段进程都会被阻塞

非阻塞IO

发起请求后,在准备数据阶段请求立即返回,因此进程不会被阻塞,但是进程会不断询问数据有没有准备好,准备好之后就发起数据接收的请求,开始第二阶段的数据拷贝,这个阶段中进程仍然会被阻塞

同步和异步

区别在于在进行**IO operation**(第二阶段)的时候会不会将进程阻塞(这里指的是真实的数据IO的时候,比如在将kernel中准备好的数据拷贝到进程中的时候,当在网络IO的时候应该也是类似的意思)。

同步IO:

在做IO operation(指的第二阶段)的时候会阻塞进程

异步IO:

在做IO operation(指的第二阶段)的时候不会阻塞进程,等到整个过程都完成了。

因此,单纯的阻塞IO和非阻塞IO都是同步IO,因为非阻塞IO在第二阶段的时候仍然是被阻塞的,只不过在第一阶段等待数据拷贝的时候是非阻塞的。

三. 协程

https://www.fanhaobai.com/2017/11/synchronised-asynchronized-coroutine.html

1. 对于操作系统来说只有进程和线程,协程的控制由应用程序显式调度,非抢占式的

2. 协程的执行最终靠的还是线程,应用程序来调度协程选择合适的线程来获取执行权

3. 切换非常快,成本低。一般占用栈大小远小于线程(协程 KB 级别,线程 MB 级别),所以可以开更多的协程

4. 协程比线程更轻量级

5. 协程可以理解为用户态的线程

事件循环 event loop

https://rgb-24bit.github.io/blog/2019/python-coroutine-event-loop.html

https://www.bilibili.com/video/av37759434/ [这个是视频,虽然是英文但是有图画还是挺好懂的]

https://zhuanlan.zhihu.com/p/33058983 [这个是一篇知乎上的文章,写得也更详细,也比较易懂]

涉及名称:

+ task queue:任务队列

+ stack:执行栈,负责执行代码,例如渲染,IO等。

+ event loop:事件循环(这其实是一个过程,这个过程被称为事件循环)

event loop 实际上是针对于异步而言的

简述:

当主线程遇到一个异步的事件(协称或者多线程之类的),会将这些任务挂起,并stack中继续执行其他的任务。等到异步事件返回结果后,该事件就会被放到task queue的队尾。当stack中的任务执行完了之后,主线程就把task queue的队首的事件拿出来,并把这个事件的回调放入stack中执行。这整个循环往复的过程就被称为事件循环。

代码举例:

```

console.log('1');

setTimeOut(function cb(){

  console.log("2");

  }, 0);

console.log('3')

打印结果:

1

3

2

```

在上面这个例子中,明明setTimeOut延时就0,应该打印结果是 1 2 3 才对吧。但是其实,setTimeOut算是个异步,所以虽然延时0,但是它的回调函数cb(也许不能这么叫,但是感觉起来对于像我这样的小白可能容易理解一点)依然被放到了task queue而不是直接进入到stack中,然后event loop等到stack中的所有任务都执行完了,再把task queue中的function cb拿到stack中,然后才执行这个函数。

在py中,我们通过selector注册了事件和回调,但是它并不会自动执行回调, 所以需要我们主动实现一个事件循环,当当前任务结束了,去主动调用它的回调。(至于里面具体的大概可以想象一下,可能是注册完了事件和回调之后,当当前的事件执行之后,回调会被放到task queue,但是并不会被放到stack中,因此这个回调并不会被执行,需要我们实现event loop来把这个回调函数从task queue放到stack中去)

四. GIL锁

http://cenalulu.github.io/python/gil-in-python/

并不是所有的解释器都有GIL锁,例如CPython中有,但是JPython总就没有

全局解释锁 加在解释器上的,为了在解释器层面保证线程安全,所以每个线程想要执行的时候必须获取GIL锁,但是这个锁只有一个,所以导致多线程其实每个cpu只有一个内核可以被使用,所以如果程序是cpu密集型的时候,反而可能不如串行来得效率高,因为多出了许许多多的context switch的时间,如果是io密集型的,那多线程还是很有用的。

线程互斥锁和GIL的区别

1. 线程互斥锁是Python代码层面的锁,解决Python程序中多线程共享资源的问题(线程数据共共享,当各个线程访问数据资源时会出现竞争状态,造成数据混乱);

2. GIL是Python解释层面的锁,解决解释器中多个线程的竞争资源问题(多个子线程在系统资源竞争是,都在等待对象某个部分资源解除占用状态,结果谁也不愿意先解锁,然后互相等着,程序无法执行下去)。

链接:https://juejin.im/post/5b977e5c5188255c996b6fad

解决GIL锁问题

由于python年岁已大,现在很多包都是基于GIL锁的,所以现在去掉可能不太容易。

但是我们可以对不同任务采用不同办法。如下:

1. cpu密集型:可以考虑换一个,别用py了。

2. IO密集型:多线程 或者 多进程(消耗大,通信不方便)+协程

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容