一、多进程
1. fork返回两次的原因:调用fork时,操作系统把当前进程复制了一份,然后fork在父子进程分别返回了一次。
2. python的os模块内的fork只能在linux类系统上调用:
2.1 import os
2.2 pid = os.fork() # pid在子进程中为0;在父进程中为子进程的进程id。
3. multiprocessing模块
3.1 multiprocessing是跨平台版本的多进程模块。
3.2 创建子进程示例:
from multiprocessing import Process # 从multiprocessing模块导入Process类。 pid = Process(target = childFunc, args = ('test', )) # 创建一个Process实例,即表示创建了一个子进程。target成员为子进程的执行函数;args成员为参数。 pid.start() # 用于启动子进程。 pid.join() # 等待子进程结束。通常用于进程间的同步。
3.3 通过进程池创建子进程示例:
from multiprocessing import Pool # 从multiprocessing模块导入Pool类。 pids = Pool(4) # 创建最多拥有四个进程的进程池 for loop in range(4); pids.apply_async(childFunc, args = (loop, )) pids.close() # 调用join()前必须先调用close()。 pids.join() # 等待所有子进程执行结束。
4. subprocess模块
4.1 类似于linux上的system()系统调用。
5. 进程间通信
5.1 multiprocessing模块提供了Queue和Pipes等多种方式支持进程间通信。
5.2 通过Queue的put()方法向队列中写数据;通过get()方法读出队列中的数据。
二、多线程。
1. python标准库提供两个线程模块:_thread和threading。_thread是低级模块;threading是高级模块,封装自_thread模块;一般使用threading模块。
2. 启动一个线程就是创建一个Thread类的实例,并调用实例的start()方法开始执行。示例:
import threading td = threading.Thread(target = threadFunc, name = 'testThread', args = (4, )) td.start()
3. threading模块的current_thread()方法用来返回当前线程的实例。threading.current_thread().name是当前线程的名字。
4. Lock
4.1 注意:高级语言的一条语句在CPU执行时是若干条语句。
4.2 全局变量在多线程间是共享的,修改变量前需要加锁。示例:
lock = threading.Lock() # 创建Lock类的实例 lock.acquire() # 获取锁 try: do something finally: lock.release()
5. 多核CPU:
5.1 GIL锁:Global Interpreter Lock全局解释器锁。
5.2 每个进程拥有一个GIL锁。
5.3 官方CPython解释器在执行python线程前需要首先获得GIL锁,执行100条字节码后释放GIL锁,其他线程获取锁后依次执行。因此python线程不能真正利用多核。
5.4 python真正利用多核只能使用进程。