并行、并发、异步、同步、阻塞与非阻塞

几个常见概念

1.并发与并行

并发:一个时间段内,有几个程序在同一个cpu上运行,但是任意时刻只有一个程序在cpu上运行
并行:指任意时刻点,有多个程序同时运行在多个cpu上。并行的数量与cpu是一致的

举个栗子: 老王爱喝茶,泡茶是老王的日常。老王泡茶要经历几个步骤:洗茶杯、放茶叶、烧开水、倒开水。
老王泡茶有两种方式:
-方式A:老王先烧开水,在烧开水的同时,洗茶杯、放茶叶。开水烧好后,直接泡茶。其实这就是并发。
-方式B:老王有三个儿子,分别叫小甲、小乙、小丙。老王同时让小甲洗茶杯、让小乙放茶叶、让小丙烧开水,自己就只管倒开水。其实这就是并行。

2.同步与异步

同步与异步 它们是消息的通知机制
A. 同步
所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。

按照这个定义,其实绝大多数函数都是同步调用(例如sin isdigit等)。
但是一般而言,我们在说同步、异步的时候,特指那些需要其他部件协作或者需要一定时间完成的任务。
最常见的例子就是 SendMessage。
该函数发送一个消息给某个窗口,在对方处理完消息之前,这个函数不返回。
当对方处理完毕以后,该函数才把消息处理函数所返回的值返回给调用者。

B. 异步
异步的概念和同步相对。
当一个异步过程调用发出后,调用者不会立刻得到结果。
实际处理这个调用的部件是在调用发出后,
通过状态、通知来通知调用者,或通过回调函数处理这个调用。

以 Socket为例,
当一个客户端通过调用 Connect函数发出一个连接请求后,调用者线程不用等待结果,可立刻继续向下运行。
当连接真正建立起来以后,socket底层会发送一个消息通知该对象。

C. 三种返回结果途径
执行部件和调用者可以通过三种途径返回结果:
a. 状态、
b. 通知、
c. 回调函数。

可以使用哪一种依赖于执行部件的实现,除非执行部件提供多种选择,否则不受调用者控制。

a. 如果执行部件用状态来通知,
那么调用者就需要每隔一定时间检查一次,效率就很低
有些初学多线程编程的人,总喜欢用一个循环去检查某个变量的值,这其实是一种很严重的错误。

b. 如果是使用通知的方式,
效率则很高,因为执行部件几乎不需要做额外的操作。

c. 至于回调函数,
和通知没太多区别。

举个栗子:
老王去银行办理业务,
当到银行后,老王有两种方式办理业务:
-方式A:可以去ATM机前排队等候 – (排队等候)就是同步等待消息
-方式B:可以去大厅拿号,等到排到我的号时,
柜台的人会通知我轮到我去办理业务. – (等待别人通知)就是异步等待消息.

3.阻塞与非阻塞

阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。
非阻塞:指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。

举个栗子:
继续老王去银行办理业务的例子,不论是排队等待,还是使用号码等待通知,如果在这个等待的过程中:
-方式A:等待者除了等待消息之外不能做其它的事情,那么该机制就是阻塞的,
在程序中的表现,也就是该程序一直阻塞在该函数调用处不能继续往下执行。
-方式B:相反,有的人喜欢在银行办理这些业务的时候一边打打电话发发短信一边等待,这样的状态就是非阻塞的,因为他(等待者)没有阻塞在这个消息通知上,而是一边做自己的事情一边等待。

多线程vs多进程

1.GIL锁

GIL,the Global Interpreter Lock,直译为“全局解释锁”。
在同一时间内,python解释器只能运行一个线程的代码,这大大影响了python多线程的性能。
因为只有当线程获得了一个全局锁的时候,那么该线程的代码才能运行。
而全局锁只有一个,所以使用python多线程,在同一时刻也只有一个线程在运行,因此即使在多核的情况下也只能发挥出单核的性能。

但是GIL锁也不能保证线程安全的,因为GIL至少会在这两种情况下释放:一是一但有IO操作时,二是当一个线程连续执行了一定数量的指令时。

2.多线程VS多进程

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_42206477/article/details/85235785