美文网首页python从小白到白痴
Python中的进程、线程、协程----详解

Python中的进程、线程、协程----详解

作者: lm_is_dc | 来源:发表于2020-03-06 17:20 被阅读0次

1、概念

从计算机硬件角度:

计算机的核心是CPU,承担了所有的计算任务。 一个CPU,在一个时间切片里只能运行一个程序。

操作系统1.jpg

图1. 操作系统

操作系统.jpg

1.1 进程

进程:是CPU对程序的一次执行过程、一次执行任务。各个进程有自己的内存空间、数据栈等。操作系统分配内存的基本单位(打开、执行、保存...)

1.2 线程

线程:是进程中执行运算的最小单位,是进程中的一个实体。(打开、执行、保存...)

一个程序至少有一个进程,一个进程至少有一个线程。

操作系统分配CPU的基本单位

1.3 协程

协程:比线程更小的执行单元,又称微线程,在单线程上执行多个任务,自带CPU上下文

用函数切换,开销极小。不通过操作系统调度,

没有进程、线程的切换开销。(gevent,monkey.patchall)

举例

我们假设把一个进程比作我们实际生活中的一个拉面馆,负责保持拉面馆运行的服务员就是线程,每个餐桌代表要完成的任务。

当我们用多线程完成任务时,模式是这样的:每来一桌的客人,就在那张桌子上安排一个服务员,即有多少桌客人就得对应多少个服务员;

而当我们用协程来完成任务时,模式却有所不同了: 就安排一个服务员,来吃饭得有一个点餐和等菜的过程,当A在点菜,就去B服务,B叫了菜在等待,我就去C,当C也在等菜并且A点菜点完了,赶紧到A来服务… …依次类推。

从上面的例子可以看出,想要使用协程,那么我们的任务必须有等待。当我们要完成的任务有耗时任务,属于IO密集型任务时,我们使用协程来执行任务会节省很多的资源(一个服务员和多个服务员的区别,并且可以极大的利用到系统的资源。

1.4 线程安全

多线程环境中,共享数据同一时间只能有一个线程来操作。

1.5 原子操作

原子操作就是不会因为进程并发或者线程并发而导致被中断的操作。

1.6 并行和并发

串行:单个CPU核心,按顺序执行

并行:多个CPU核心,不同的程序就分配给不同的CPU来运行。可以让多个程序同时执行。(多进程)

并发:单个CPU核心,在一个时间切片里一次只能运行一个程序,如果需要运行多个程序,则串行执行,遇到IO阻塞就切换,即计算机在逻辑上能处理多任务的能力。(多进程,多线程)

并行并发.jpg

1.7 多进程/多线程

表示可以同时执行多个任务,进程和线程的调度是由操作系统自动完成

进程:每个进程都有自己独立的内存空间,不同进程之间的内存空间不共享。

线程:一个进程可以有多个线程,所有线程共享进程的内存空间,通讯效率高,切换开销小。共享意味着竞争,导致数据不安全,为了保护内存空间的数据安全,引入"互斥锁",“递归锁”,“升序锁”等。

并发.jpg 多线程与协程区别.jpg

1.8 Python的多线程:

GIL:Global Interpreter Lock, 全局解释器锁,线程的执行权限,在Python的进程里只有一个GIL。

Gil锁.jpg gil线程竞争.jpg

一个线程需要执行任务,必须获取GIL。

好处:直接杜绝了多个线程访问内存空间的安全问题。

坏处:Python的多线程不是真正多线程,不能充分利用多核CPU的资源。

但是,在I/O阻塞的时候,解释器会释放GIL。

1.9 同步、异步、阻塞、非阻塞

同步非阻塞.jpg 阻塞.jpg 异步非阻塞.jpg
异步阻塞.jpg

异步,异步本质上是单线程的,因为 IO 操作在很多时候会存在阻塞,异步就是在这种阻塞的时候,通过控制权的交换来实现多任务的。即异步本质上是运行过程中的控制权的交换。最典型的例子就是生产者消费者模型。

同步,即程序协同进行,遇到阻塞就等待,直到任务完成为止。

2.0 运用场景

多进程:密集CPU任务,需要充分使用多核CPU资源(服务器,大量的并行计算)的时候,用多进程。 multiprocessing

缺陷:多个进程之间通信成本高,切换开销大。

多线程:密集I/O任务(网络I/O,磁盘I/O,数据库I/O)使用多线程合适。

threading.Thread、multiprocessing.dummy

缺陷:同一个时间切片只能运行一个线程,不能做到高并行,但是可以做到高并发。

多线程与多进程运用场景.jpg

协程:又称微线程(一种用户态的轻量级线程),在单线程上执行多个任务,用函数切换,由程序自身控制,开销极小。

不通过操作系统调度,没有进程、线程的切换开销。

每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置,不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。

当程序中存在大量不需要CPU的操作时(IO),遇到IO操作自动切换到其它协程。

greenlet, gevent,monkey.patchall,yield,async

多线程请求返回是无序的,哪个线程有数据返回就处理哪个线程,而协程返回的数据是有序的。

因为协程是一个线程执行,所以想要利用多核CPU,最简单的方法是多进程+协程,这样既充分利用多核,又充分发挥协程的高效率。

缺陷:单线程执行,处理密集CPU和本地磁盘IO的时候,性能较低。处理网络I/O性能还是比较高.

2.1 互斥锁、递归锁、升序锁

Python的GIL只能保证原子操作的线程安全,因此在多线程编程时我们需要通过加锁来保证线程安全。

最简单的锁是互斥锁(同步锁),互斥锁是用来解决IO密集型场景产生的计算错误,即目的是为了保护共享的数据,同一时间只能有一个线程来修改共享的数据。

递归锁:就是在一个大锁中再包含子锁

升序锁:两个线程想获取到的锁,都被对方线程拿到了,那么我们只需要保证在这两个线程中,获取锁的顺序保持一致就可以了。举个例子,我们有线程thread_a, thread_b, 锁lock_1, lock_2。只要我们规定好了锁的使用顺序,比如先用lock_1,再用lock_2,当线程thread_a获得lock_1时,其他线程如thread_b就无法获得lock_1这个锁,也就无法进行下一步操作(获得lock_2这个锁),也就不会导致互相等待导致的死锁。简言之,解决死锁问题的一种方案是为程序中的每一个锁分配一个唯一的id,然后只允许按照升序规则来使用多个锁,这个规则使用上下文管理器 是非常容易实现的。

相关文章

  • python笔记3

    python 无线程池 ,有进程池 阻塞 意外着等待子进程结束 字典的无序性 : 进程,线程,协程 协程,又称微...

  • Gevent高并发网络库精解

    进程 线程 协程 异步 并发编程(不是并行)目前有四种方式:多进程、多线程、协程和异步。 多进程编程在python...

  • Python 中的进程、线程、协程详解

    目录 [toc] 概念 CPU在同一时刻只能处理一个任务,cpu在各个任务之间来回的进行切换,只是因为cpu执行速...

  • Python中的进程、线程、协程----详解

    1、概念 从计算机硬件角度: 计算机的核心是CPU,承担了所有的计算任务。 一个CPU,在一个时间切片里只能运行...

  • GO学习笔记(18) - 并发编程(1) - 理解gorouti

    目录 进程、线程与协程 并发模模型介绍 GO并发编程介绍 进程、线程与协程 进程和线程 进程是程序在操作系统中的一...

  • Python-02进阶-04多进程多线程

    Python 进阶-04 进程线程协程并发等.md tags: Python 多进程 并发 进阶 必备知识 201...

  • python多线程、多进程、协程的使用

    python多线程、多进程、协程的使用 本文主要介绍多线程、多进程、协程的最常见使用,每个的详细说明与介绍有时间会...

  • Python - 进程、线程与协程

    Python - 高级教程 - 进程、线程与协程 进程与线程 在操作系统中,每一个独立运行的程序,都占有 操作系统...

  • 浅析python的GIL

    Python中的GIL锁 在Python中,可以通过多进程、多线程和多协程来实现多任务。 在多线程的实现过程中,为...

  • Unity协同函数简介

    协程的概念 协程又可以称为用户线程,微线程,可以将其理解为单个进程或线程中的多个用户态线程,这些微线程在用户态进程...

网友评论

    本文标题:Python中的进程、线程、协程----详解

    本文链接:https://www.haomeiwen.com/subject/nrswrhtx.html