Python 中的协程 (3) 基础概念

1 进程和线程

进程 Process:一个正在运行的应用程序在操作系统中被视为一个进程,进程可以包括一个或多个线程。线程是操作系统分配处理器时间的基本单元,在进程中可以有多个线程同时执行代码。进程之间是相对独立的,一个进程无法访问另一个进程的数据(除非利用分布式计算方式)。

线程 Thread: 线程是进程中的基本执行单元,是操作系统分配CPU时间的基本单位,一个进程可以包含若干个线程,在进程入口执行的第一个线程被视为这个进程的主线程。线程主要是由CPU寄存器、调用栈和线程本地存储器(Thread Local Storage,TLS)组成的。CPU寄存器主要记录当前所执行线程的状态,调用栈主要用于维护线程所调用到的内存与数据,TLS主要用于存放线程的状态信息。线程的本质:线程不是一个计算机硬件的功能,而是操作系统提供的一种逻辑功能,线程本质上是进程中一段并发运行的代码,所以线程需要操作系统投入CPU资源来运行和调度。

进程和线程的区别:进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

  1. 一个程序至少有一个进程,一个进程至少有一个线程。
  2. 线程的划分尺度小于进程,使得多线程程序的并发性高。
  3. 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
  4. 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
  5. 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别

2 同步(Sync)和异步(Async)

同步 :就是发出一个功能调用时,在没有得到结果之前,该调用就不返回或继续执行后续操作。

异步 :当一个异步过程调用发出后,调用者在没有得到结果之前,就可以继续执行后续操作。当这个调用完成后,一般通过状态、通知和回调来通知调用者。对于异步调用,调用的返回并不受调用者控制。

对于通知调用者的三种方式,具体如下:

  1. 状态,即监听被调用者的状态(轮询),调用者需要每隔一定时间检查一次,效率会很低。
  2. 通知,当被调用者执行完成后,发出通知告知调用者,无需消耗太多性能
  3. 回调,与通知类似,当被调用者执行完成后,会调用调用者提供的回调函数。

同步和异步的区别 : 请求发出后,是否需要等待结果,才能继续执行其他操作。

3 阻塞和非阻塞

阻塞和非阻塞这两个概念仅仅与等待消息通知时的状态有关。跟同步、异步没什么太大关系,也就是说阻塞与非阻塞主要是程序(线程)等待消息通知时的状态角度来说的。

阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。

阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。

非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

4 并发并行

并发: 是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。并发(Concurrent)。

并行:当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。

并发和并行的区别:并发的关键是你有处理多个任务的能力,不一定要同时;但是并行的关键是你有同时处理多个任务的能力。

5 关键概念的区分

(1)阻塞/非阻塞:关注的是程序在等待调用结果(消息,返回值)时的状态

(2)同步/异步:关注的是消息通知的机制。即等到完全做完才通知,还是边做不后通知。

(3)同步阻塞、同步非阻塞,异步阻塞、异步非阻塞。

  举个简单的例子来描述这四种情况,老张要做两件事,用水壶烧开水,看电视,两件事情即两个任务,两个函数。 同步阻塞:老张把水壶放到火上,就坐在那里等水开,开了之后我再去看电视。() 同步非阻塞:老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞) 老张还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀~~~~的噪音。 异步阻塞:老张把响水壶放到火上,然后就坐在旁边等着听那个烧开的提示音。(异步阻塞) 异步非阻塞:老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞) 乍一看,这“同步阻塞、意不阻塞”似乎没有什么区别,但实际上是有区别的,所谓同步异步,指的是消息通知的机制。区别在哪里呢? 在这个例子中同步异步只是对于水壶而言。在使用普通水壶的时候,我要自己主动去观察水是不是烧开了,自己主动去获取烧开的这个结果,即所谓的同步;但是在响水壶的时候,我不需要再管水烧到什么程度了,因为只要水烧开了,那个滴滴的噪声就会通知我的,即所谓的异步。 他们的相同点是,在烧水的过程中,老王啥也没干,即“阻塞”。

(4)四种总结——同步/异步与阻塞/非阻塞

  同步阻塞形式:效率是最低的。拿上面的例子来说,在烧水的过程中,什么别的事都不做。

    同步非阻塞形式:实际上是效率低下的。因为老王需要不断的在看电视与烧水之间来回跑动,看一下电视,又要去看一下水烧开没有,这样来回跑很多次,在程序中,程序需要在这两种不同的行为之间来回的切换,效率可想而知是低下的。

  异步阻塞形式:异步操作是可以被阻塞住的,只不过它不是在处理消息时阻塞,而是在等待消息通知时被阻塞。 这个效率其实跟同步阻塞差不多的。

  异步非阻塞形式:效率更高。因为老王把水烧好之后就不用管了,可以安安心心去看电视,不用来回奔波看水烧开了没,因为水烧开了会有提示告诉他水烧好了,这样效率岂不是更高。 那有没有更好的办法?当然有,如果老王还有一个帮手老张,让老王自己看电视、同时老张去烧开水,这样岂不是更好?这就是所谓的并行

(5)并发/并行、同步/异步、阻塞/非阻塞

  并发/并行:即能够开启多个任务,多个任务交替执行为并发,多个任务同时执行为并行

  同步/异步:关注的是消息通知的机制,主动等候消息则为同步、被动听消息则为异步

  阻塞/非阻塞:关注的是等候消息的过程中有没有干其他事。

  总结:上面的几组概念,时刻穿插的,并没有完全的等价关系,所以经常有人说,异步就是非阻塞,同步就是阻塞,并发就是非阻塞、并行就是非阻塞,这些说法都是不完全准确地。

6 总结

并发和并行都是实现异步编程的思路,只有一个线程的并发,称之为“伪并发”;有多个线程的并发称之为“真并发”,真并发与并行是很接近的。

异步操作的优缺点 :

  因为异步操作无须额外的线程负担(这里指的是单线程交替执行的“伪并发”),并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少 共享变量的数量),减少了死锁的可能。当然异步操作也并非完美无暇。编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,与普通人的思维方式有些 初入,而且难以调试。

多线程的优缺点:

  多线程的优点很明显,线程中的处理程序依然是顺序执行,符合普通人的思维习惯,所以编程简单。但是多线程的缺点也同样明显,线程的使用(滥用)会给系统带来上下文切换的额外负担。并且线程间的共享变量可能造成死锁的出现。 异步与多线程,从辩证关系上来看,异步和多线程并不时一个同等关系,(因为单线程也是可以实现异步的)异步是目的,多线程只是我们实现异步的一个手段.什么是异步:异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回.实现异步可以采用多线程技术或则交给另外的进程来处理。

  

原文地址:https://www.cnblogs.com/wang-kai-1994/p/10375229.html

时间: 2024-10-11 13:19:21

Python 中的协程 (3) 基础概念的相关文章

协程及Python中的协程

阅读目录 1 协程 2 Python中如何实现协程 回到顶部 1 协程 1.1协程的概念 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程.(其实并没有说明白~) 我觉得单说协程,比较抽象,如果对线程有一定了解的话,应该就比较好理解了. 那么这么来理解协程比较容易: 线程是系统级别的,它们是由操作系统调度:协程是程序级别的,由程序员根据需要自己调度.我们把一个线程中的一个个函数叫做子程序,那么子程序在执行过程中可以中断去执行别的子程序:别的子程

Python 中的协程 (5) 无阻塞

1 异步程序依然会假死 freezing 1)一般程序的调用方 freezing import asyncio import time import threading #定义一个异步操作 async def hello1(a,b): print(f"异步函数开始执行") await asyncio.sleep(3) print("异步函数执行结束") return a+b #在一个异步操作里面调用另一个异步操作 async def main(): c=await

python中的协程

1 协程 1.1协程的概念 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程.(其实并没有说明白~) 我觉得单说协程,比较抽象,如果对线程有一定了解的话,应该就比较好理解了. 那么这么来理解协程比较容易: 线程是系统级别的,它们是由操作系统调度:协程是程序级别的,由程序员根据需要自己调度.我们把一个线程中的一个个函数叫做子程序,那么子程序在执行过程中可以中断去执行别的子程序:别的子程序也可以中断回来继续执行之前的子程序,这就是协程.也就是说同一

python中的协程(协同程序)

协程:将函数编写为一个能处理输入参数的任务 使用yield语句并以表达式yield的形式创建协程 #匹配器案例: def print_info(data):    print('Looking for',data);    while True:      line = (yield)      if data in line:        print(line); 上面这个函数 就是一个协程程序 要使用这个函数 首先需用调用它 并且 向前执行到第一条yield语句 info = print_

Python 中的协程 (2) yield from

1 yiled from 的定义 从字面看是yield的升级改进版本,如果将 yield 理解成返回,那么 yield from 就是从哪里返回. def generator2(): yield 'a' yield 'b' yield 'c' yield from [11,22,33,44] yield from (12,23,34) yield from range(3) for i in generator2(): print(i,end=' , ') # a , b , c , 11 ,

Python与Golang协程异同

背景知识 这里先给出一些常用的知识点简要说明,以便理解后面的文章内容. 进程的定义: 进程,是计算机中已运行程序的实体.程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 线程的定义: 操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位. 进程和线程的关系: 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. CPU的最小调度单元是线程不是进程,所以单进程多线程也可以利用多核CPU. 协程的定义: 协

在PHP中使用协程实现多任务调度

PHP5.5一个比较好的新功能是加入了对迭代生成器和协程的支持.对于生成器,PHP的文档和各种其他的博客文章已经有了非常详细的讲解.协程相对受到的关注就少了,因为协程虽然有很强大的功能但相对比较复杂, 也比较难被理解,解释起来也比较困难. 这篇文章将尝试通过介绍如何使用协程来实施任务调度, 来解释在PHP中的协程. 我将在前三节做一个简单的背景介绍.如果你已经有了比较好的基础,可以直接跳到“协同多任务处理”一节. 迭代生成器 生成器也是一个函数,不同的是这个函数的返回值是依次输出,而不是只返回一

Python并发之协程

<python并发之协程>一: 单线程下实现并发,即只在一个主线程,并且cpu只有一个的情况下实现并发.(并发的本质:切换+保存状态) cpu正在运行一个任务,会在两种情况下切去执行其他的任务(切换由操作系统强制控制),一种情况是该任务发生了阻塞,第二种情况是该任务计算时间过长. 主线程的三种状态:其中第二种情况并不能提升效率,只是为了让cpu能够雨露均沾,实现看起来大家都被执行的效果,如果多个程序都是纯计算任务,这种切换反而会降低效率.为此我们基于yield验证.yield本身就是一种在单线

python并发编程&amp;协程

0x01 前导 如何基于单线程来实现并发? 即只用一个主线程(可利用的cpu只有一个)情况下实现并发: 并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去执行其他的任务(切换由操作系统强制控制),一种情况是该任务发生了阻塞,另外一种情况是该任务计算的时间过长 ps:在介绍进程理论时,提及进程的三种执行状态,而线程才是执行单位,所以也可以将上图理解为线程的三种状态 1)其中第二种情况并不能提升效率,只是为了让cpu能够雨露均沾,实现看起来所有任务都被“同时”执行的效果,如果多