多进程,多线程及其模块

2018-08-23  本文已影响36人  HHHHUA

1. 进程

进程:计算机中一个程序在一个数据集上一次动态执行过程,主要包含三部分内容

⚫ 程序:描述进程的功能以及处理流程

⚫ 数据集:功能处理过程中需要的资源数据

⚫ 进程控制:严格控制进程执行过程中的各种状态

通俗来说,一个进程就是计算机上正在运行的一个程序

2. 线程

计算机中程序运行的实际执行者就是线程,线程又称为轻量级进程,是一个CPU的执行单 元,每个进程至少会有一个主线程用于执行程序

线程和进程对比如下:

⚫ 一个进程可以有多个线程,但是至少有一个主线程

⚫ 一个线程只能属于一个进程

⚫ 一个进程中多个线程,可以共享进程中提供的数据

⚫CPU 运算分配给线程,CPU 上执行运算的是线程

⚫ 线程是最小的运行单元,进程是最小的资源管理单元

3. 串行、并行、并发

串行:就是传统意义上的同步、顺序的意思,按照一定的执行步骤顺序执行每个环节

并行:就是传统意义上的异步、同时的意思,同时执行接受到的多个任务

并发:同时接收到多个任务,同时执行多个任务,但是具体到某个时刻~只是在执行一个任 务,只是在很短时间内在多个任务之间切换,模拟形成了多个任务同时执行的现象

4. 多线程编程

PYTHON本身对于多线程并发机制的支持是比较完善的

在PYTHON2中提供了标准模块 thread 和 threading 支持多线程的并发编程 但是随着并发编程的实际使用操作过程,thread 模块过于底层的控制方式对于并发编程的 新手来说挺不是非常友好,要求多线程的程序开发逻辑思维清晰同时又具备大量开发经验的 情况下,可以控制的非常精细。

PYTHON3中将 thread 模块进行了规范内置,更名为_thread,友好的提醒如果你不是并发编 程的骨灰级爱好者,请不要轻易尝试使用_thread 进行操作,而是推荐使用操作更加灵活使 用更加简洁的 threading 模块进行并发编程的处理。

1. Threading模块属性和方法

名称                描述

Thread             线程类,用于创建和管理线程

Event                 事件类,用于线程同步

Condition            条件类,用于线程同步

Lock/RLock            锁类,用于线程同步

Timer             延时线程,用于在一定事件后执行一个函数

Semaphore/BoundedSemaphore        信号量类,用于线程同步

active_count()/activeCount()         获取当前

alive             状态的所有线程数量

current_thread()/currentThread()        获取当期正在执行的线程对象

get_ident()           获取运行中程序当前线程的唯一编号

enumerate()            获取所有

alive           状态线程列表

local             线程局部数据类

stack_size([size])           获取线程占用内存栈的大小

main_thread()           获取主线程

2. Thread类型属性和方法

名称            描述

__init__(group,target,name,args,kwargs)      构造方法,创建线程类型

is_alive()/isAlive()          判断当前线程是否

alive           状态

run()             线程执行方法,自定义线程必须重写该函数

start()             线程启动方法

join([timeout=None])          线程独占,等待当前线程运行结束或者超时

ident             标识当前线程的唯一编号

name           当前线程名称

daemon             布尔值,判断当前线程是否守护线程

3. 线程管理-事件[Event]

线程锁解决了多个线程访问共享数据时冲突的问题,如果多个线程之间需要通信应该怎么解决呢?此时就需要用到多个线程之间的可以用于互相通信的处理对象了,该处理对象必须满足如下基本条件

⚫ 该对象能同时被多个线程访问

⚫ 该对象可以被标记不同的状态

⚫ 该对象可以用于控制线程等待|运行之间的切换

python提供了一个事件对象 Event,可以基本满足上述条件,完成线程之间的通信

名称         描述

set()           添加一个标记状态

isSet()/is_set()        检查事件对象是否被标记

clear()           清除标记状态

wait()           事件对象操作的当前线程等待,直到该对象被标记状态

4. 线程管理-条件[Condition]

线程条件Condition对象,也是多线程并发模式下一种线程之间通信的友好支持 在某些情况下,我们需要多个线程在运行过程中根据实际操作情况,不同功能的线程在满足 对应的条件时等待、启动两种状态之间进行切换

如经典的线程间通信问题:生产者消费者问题生产者负责生产食物,将食物存储在列表中;消费者负责消费,也就是从列表中删除数据;

这里的存储食物的列表,我们限制了长度,最多容纳20个食物数据

此时就会出现这样的问题:如果列表中的食物已经达到20;那么所有的生产者线程不能继 续生产食物了,必须处于等待状态,等待消费者消费了食物之后再次生产 同理,如果列表中的食物为空了,所有的消费者也就不能吃食物了,必须处于等待状态;等 待生产者生产了食物之后才能消费

Condition对象的属性和方法

名称          描述

acquire()          锁定

release()          解锁

wait()           释放锁,同时阻塞当前线程,等待被唤醒

wait_for()          释放锁,同时阻塞当前线程,等待被唤醒

notify()           唤醒

notify_all()         唤醒所有等待该condition条件的线程

5. 线程管理-队列[Queue]

多线程并发编程的重点,是线程之间共享数据的访问问题和线程之间的通信问题为了解决线程之间数据共享问题,PYTHON提供了一个数据类型【队列】可以用于在多线程 并发模式下,安全的访问数据而不会造成数据共享冲突

python中的 queue 模块提供的队列类型 Queue 的操作模式如下

名称                描述

put([timeout=None])             向队列中添加数据,队列如果满了,一直阻塞直到超时或者队 列中有数据被删除之后添加成功

get([timeout=None])          从队列中获取数据,如果队列为空,一直阻塞直到超时或者队列中添加数据之后获取成功

6. 线程管理-其他

PYTHON提供的线程同步管理方式还有其他的操作处理类型,操作方式都是大同小异,也分 别适用于不同的场景

名称                    描述

Semaphore            线程锁计数器调用acquire()方法时该计数器减 1,调用 release()方法时计数器加 1 适用于控制线程访问数量的场景下

BoundedSemaphore           Semaphore的派生类/子类,支持 with 关键字操作功能和使用场景同上

Barrier             线程协同类型wait()方法:比较特殊,程序中的每个线程都可以调用该wait()方法,让当前 线程处于等待状态;直到所有的线程全部调用了wait()方法之后,所有线程同时唤醒继续执行。比较适用于数据预处理工作的场景

5. 多进程编程

进程是正在执行中的应用程序,一个进程包含了该应用程序的所有信息,如加载数据内存空间、代码、程序数据、对象句柄,执行单元等等,一个应用程序根据其功能的多样性,可以通过多个进程并发的形式来实现。

计算机中多线程的操作已经可以实现多任务的处理机制了,但是如果涉及到多核CPU或者 多个 CPU 的硬件主机,多进程并发编程的实现能比多线程并发机制更加有效的利用和发挥 硬件资源优势。

1. Multiprocessing

PYTHON内建标准模块 multiprocessing 对多进程并发编程提供了良好的支持,通过该模块 的 Process 进程类型,可以很方便的创建和管理多个进程;通过该模块提供的 Lock|RLock 进 程锁类型、Event 事件类型、Condition 条件类型等等也可以很方便的完成进程间同步操作。

和多线程的操作方式类似,多进程的实现方式也提供了面向过程的实现和面向对象的实现同时多进程的本地数据共享和通信模式也非常的类似多线程编程

multiprocessing常见属性和方法

名称                 描述

Process              进程类型,用于创建和管理进程

Lock|RLock             进程互斥锁|重用锁,用于进程同步

Event                  进程事件类型,用于进程同步

Condition                 进程条件类型,用于进程同步

Queue                  进程队列类型,用于多进程数据共享

Manager                  进程管理类型,用于多进程数据共享

Listener|Client                进程监听|客户端,基于网络多进程之间的数据共享

2. Multiprocessing

多进程的操作在实际应用中也是非常多的,但是纯底层的代码开发控制并发也是一件非常繁琐的事情,所以就出现了面向过程多进程并发的优化操作方式:进程池Pool

通过进程池Pool可以快速创建多个进程执行指定函数,完成高并发处理操作

(1) Pool对象的属性和方法

名称             描述

apply(func, args)        传递参数args并执行函数 func,同时阻塞当前进程直到该函数执行完成,函数func只会在进程池中的一个进程中运行

apply_async(   func,args,callback, error_callback  )                          传递参数args并执行函数 func,该方法不会形成阻塞函数执行完成之后可以通过结果对象的get()方法获取结果如果结果对象可用时会自动调用callback指定的函数如果结果对象调用失败时会自动调用error_callback指定的函数

close()                      Pool进程池的底层工作机制是向进程池提交任务产生工作进程执行该方法是主动停止给进程池提交任务,并等待所有提交任务执行完成退出

terminate()                 立即结束该进程,当进程池对象被回收时自动调用该方法

join()                          等待工作进程退出,再次之间必须调用close()或者 teminate

3. 多个进程通信:multiprocessing.Manager

不同线程之间的数据通信,涉及到核心的数据共享问题,主要由PYTHON中提供的内建模 块 multiprocessing.Manager 类型实现,该类型内置了大量的用于数据共享的操作

multiprocessing.Manager常见属性和方法   

名称               描述

Array                内置进程间共享数组类型

Queue                内置进程间共享队列类型

list()                    内置进程间共享列表类型

dict()                    内置进程间共享字典类型

Value                    内置进程间共享值类型

Barrier                        进程同步类型

BoundedSemaphore| Semaphore      进程信号量类型

Lock|RLock               进程互斥锁/重用锁

Event                进程同步事件类型

Condition               进程同步条件类型

多个进程之间的通信操作,数据的传递在PYTHON中的 multiprocessing 模块中提供了一个 专门用于多进程之间进行数据传递的队列:Queue

4. 多个进程通信:multiprocessing.Queue

multiprocessing.Queue常见属性和方法

名称              描述

put(data [, timeout=None])           添加一个数据到队列中

put_nowait(data)                     添加一个数据到队列中,非阻塞模式

get([timeout=None])            从队列中获取一个数据

get_nowait()                  从队列中获取一个数据,非阻塞模式

full()                           判断队列是否已满

empty()                   判断队列是否已空

close()                   关闭队列

qsize()                   获取队列中的元素数量

5. 多个进程通信:multiprocessing.Pipe

PYTHON为了更加友好的多个进程之间的数据通信操作,提供了一个管道类型专门用于进程之间的协作:multiprocessing.Pipe

multiprocessing.Pipe常见属性和方法

名称                描述

__init__(duplex=True)                 初始化方法,返回两个数据conn1,conn2分别表示管道的两端,默认是双向通信如果duplex=False conn1只能接受消息,conn2只能发送消息

send(data)                                   发送消息

recv()                                            接受消息

上一篇下一篇

猜你喜欢

热点阅读