python的进程、线程、协程

本文详细介绍了Python中的进程、线程和协程。进程是资源分配的基本单位,线程是程序执行的最小单位,而协程则提供了一种高效的任务切换方式。在Python中,进程间通讯可以通过Queue实现,线程同步可以使用锁和队列。由于GIL的存在,多线程在Python中主要用于IO密集型任务,多进程适用于计算密集型任务。此外,文章还讨论了如何使用多进程和协程处理CPU密集型任务,以及在galaxy项目中如何配置uWSGI以利用多进程和多线程来提高并行处理能力。
摘要由CSDN通过智能技术生成
进程与线程

单核的CPU在一个时间片中只能执行一个程序,各个程序之间抢夺CPU资源
进程:进程就是一个程序在数据集上的一次动态执行过程,进程是资源分配的基本单位。程序运行时,系统会创建一个进程,并为进程分配资源。

线程:复杂代码块的执行,是程序执行的最小单位,也是进程中一个执行路径,每个线程都有自己的任务代码

进程与线程的关系

  1. 线程不可独立存在,需要依赖进程
  2. 一个进程可以有多个线程,多个线程共享进程的资源;多个进程间资源是独立的(CPU切换一个线程花费的开销比切换进程小,同时创建一个线程的开销也比进程小)
  3. 每个进程有独立的资源,当一个进程崩溃时,对其他进程没有影响–进程的稳定性高;但任何一个线程挂掉可能会造成进程崩溃,因为多个线程共享一个进程资源
  4. 由于GIL锁的缘故,python 中线程实际上是并发运行(即便有多个cpu,线程会在其中一个cpu来回切换,只占用一个cpu资源),而进程才是真正的并行(同时执行多个任务,占用多个cpu资源)
  5. IO密集型使用多线程(在等待时切换),计算密集型使用多进程(充分利用多核CPU)

并行与并发

  1. 并行:是指两个或者多个事件在同一时刻发生
    1. python中的进程属于并行
    2. 当一个CPU执行一个进程时,另一个CPU可以执行另一个进程
    3. 两个进程互不抢占CPU资源,能充分利用计算机资源,效率最高
  2. 并发:并发是指两个或多个事件在同一时间间隔发生
    1. python中的线程属于并发。
    2. 不管计算机有多少个CPU,不管你开了多少个线程,同一时间多个任务会在其中一个CPU来回切换,只占用一个CPU,效率并不高;
1、进程
1.1、进程的状态

任务数(进程数)往往大于cpu的核数,即一定有一些任务正在执行,而另外一些任务在等待cpu进行执行,因此导致了有了不同的状态

  1. 就绪态:运行的条件符合,正在等在空闲cpu执行
  2. 执行态:cpu正在执行其功能
  3. 等待态(阻塞):等待某些条件满足,例如一个程序sleep了,此时就处于等待态(再比如一些需要花费时间来等待来自用户、文件、数据库、网络等的输入输出的任务)
  4. 死亡
1.2、创建进程

创建进程的类:Process([group [, target [, name [, args [, kwargs]]]]])

  1. target表示调用对象
  2. args表示调用对象的位置参数元组
  3. kwargs表示调用对象的字典
  4. name为别名
  5. group实质上不使用。

进程的方法

  1. is_alive()
  2. join([timeout])
    join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步
  3. run()
  4. start()
    Process以start()启动某个进程
  5. terminate()。
import multiprocessing
import time

def worker(interval):
    n = 5
    while n > 0:
        print("The time is {0}".format(time.ctime()))
        time.sleep(interval)
        n -= 1

if __name__ == "__main__":
    p = multiprocessing.Process(target = worker, args = (3,))
    p.start()
    print "p.pid:", p.pid
    print "p.name:", p.name
    print "p.is_alive:", p.is_alive()
1.3进程池

如果想要启动大量的子进程,可以用进程池的方式批量创建子进程

  1. 主进程或者主线程会等待子进程或者子线程执行完毕后结束

  2. 创建进程池后,主进程不会等待进程池中的代码执行完

  3. 可以使用进程池的.join()方法等待子进程执行完

    1. p = Pool() 创建进程池,默认创建4个,如果想要更多,加上参数即可:p = Pool(8)
    2. p.close() 调用close()方法后,就不能再创建进程了
    3. p.join() 会等待所有子进程执行完毕
from multiprocessing import Pool

if __name__=='__main__':
    print 'Parent process %s.' % os.getpid()
    p = Pool()   #创建进程池,默认创建4个
    for i in range(5):
        p.apply_async(func_name, args=(i,))
    print 'Waiting for all subprocesses done...'
    p.close()  # 调用close方法后,就不能再创建进程了
    p.join()  #会等待所有子进程执行完毕
    print 'All subprocesses done.'
  1. 进程 0,1,2,3是立刻执行的
  2. task 4要等待前面某个task完成后才执行
  3. 进程池Pool的默认大小是4,最多同时执行4个进程,Pool的默认大小是CPU的核数
1.4进程间通讯

进程间的通讯可以通过socket、文件读写、Queue队列完成

队列:队列类似于一条管道,元素先进先出。队列都是在内存中操作:进程退出,队列清空(队列是一个阻塞的形态)

以下,创建两个子进程,一个往队列里写数据,一个从队列里读数据:

from multiprocessing import Process, Queue
import os, time, random

# 写数据进程执行的代码:
def write(q):
    for value in ['A', 'B', 'C']:
        print 'Put %s to queue...' % value
        q.put(value)
        time.sleep(random.random())

# 读数据进程执行的代码:
def read(q):
    while True:
        value = q.get(True)
        print 'Get %s from queue.' % value

if __name__=='__main__':
    # 父进程创建Queue,并传给各个子进程:
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    # 启动子进程pw,写入:
    pw.start()
    # 启动子进程pr,读取:
    pr.start()
    # 等待pw结束:
    pw.join()
    # pr进程里是死循环,无法等待其结束,只能强行终止:
    pr.terminate()
2、线程
2.1、线程的实现方式

绝大多数情况下,我们只需要使用threading这个高级模块。

实现方式有两种:
(1)函数式
启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行

import time, threading

# 新线程执行的代码:
def loop():
    print('thread %s is running...')

print('thread %s is running...' )
t = threading.Thread(target=loop, name='LoopThread')
t.start()  # 启动一个线程
t.join()   # 等待所有线程执行完毕
print('thread %s ended')

2)类式

import threading,time
# myThread类继承了线程类threading.Thread,可以重写run方法
class myThread(threading.Thread):
    def __init__(self, name):
        super().__init__()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值