1、如何使用多线程?
实际案例:
由于python中全局解释器锁(GIL)的存在,在任意时刻只允许一个线程在解释器中运行。因此python的多线程不适合处理cpu密集型的任务。
想要处理cpu密集型的任务,可以使用多进程模型。
解决方案:
使用标准库中multiprocessing.Process,它可以启动子进程执行任务,操作接口,进程间通信,进程间同步等,都与Threading.Thread类似。
2、代码演示
(1)进程简单使用
# _*_ encoding:utf-8 _*_
from multiprocessing import Process
# 定义需要子进程执行函数
def f(s):
print(s)
# 创建一个全局变量
x = 1
# 在f2函数内部修改全局变量的值
def f2():
# 使用global声明x,然后再修改成5
global x
x = 5
if __name__ == '__main__':
# 创建子进程执行函数
p = Process(target=f, args=('hello',))
# 启动子进程
p.start()
# 等待一个进程结束
p.join()
'''
和多线程不一样的是多个进程之间他们使用的虚拟地址空间是独立的。
'''
# 在本进程中调用f2,然后查看x发现变成了5
f2()
print(x)
# 将x再修改回去,启动子进程修改
x = 1
p1 = Process(target=f2)
p1.start()
# 在主进程当中查看x是1还是5
print(x)
# 发现x=1,说明子进程和主进程他们看到的,x不是同一个x他们分别是独立的
# 既然进程之间无法访问彼此的地址空间,进程之间如何通信
(2)Queue队列和Pipe管道的简单使用
# _*_ encoding:utf-8 _*_
from multiprocessing import set_start_method
# 导入进程、队列和管道
from multiprocessing import Process, Queue, Pipe
# 注意Queue和queue.Queue并不是同一个对象
q = Queue()
q.put(1)
print(q.get())
def f(q1):
print('start')
# 等待主进程传入一个值
print(q1.get())
print('end')
# Pipe会创建双向的管道
c1, c2 = Pipe()
# 向管道的c1端传入数据,在c2端读取出来
c1.send('abc')
print(c2.recv())
# c2端写入的,从c1端读取出来
c2.send('xyz')
print(c1.recv())
def f2(c):
# 从连接中读取数据,然后乘2再写回去
c.send(c.recv() * 2)
if __name__ == '__main__':
'''
set_start_method为创建进程的方式:
fork为分支创建,spawn为分产创建。
'''
set_start_method('fork', True)
# ------------------------------
q2 = Queue()
# 启动一个子进程直接运行
Process(target=f, args=(q2,)).start()
# 子进程阻塞到get,等待传入一个值
q2.put(100)
# ------------------------------
c3, c4 = Pipe()
# 子进程会等待向管道写
Process(target=f2, args=(c4,)).start()
# 从c3端写入数据,然后函数回返回回来,再在c3端读取
c3.send(55)
print(c3.recv())