Python的线程、进程、协程
当涉及到并发编程时,Python 提供了多种机制来实现并发执行的效果,包括线程、进程和协程
一、概念区分
- 进程:
- 是CPU对程序的一次执行过程、一次执行任务
- 操作系统分配内存的基本单位
- 线程
- 是进程中执行运算的最小单位
- 操作系统分配CPU的基本单位
- 协程
- 比线程更小的执行单元,又称微线程,由程序员手动控制执行的切换
- 用函数切换,开销极小。不通过操作系统调度
二、实现
宋宋老师总结:
进程,线程:
Process类
创建进程:
def func(n):
pass
p = Process(target=func,name='',args=(1,),kwargs='')
p.start()
run()
class MyProcess(Process):
def run(self):
pass
p = MyProcess()
p.start()
进程数据共享:
n=0
进程池: Pool
p= Pool(5)
阻塞式 apply(func,args,kwargs)
非阻塞式 apply_async(func,args,kwargs,callback=函数)
进程间通信
Queue()
q = Queue(4)
q.put()
q.get()
q.qsize()
q.empty()
q.full()
线程:
包含关系
进程里面可以存着多个线程,多个线程共用进程资源
GIL: 全局解释器锁
线程: ’伪线程‘
线程:Thread
1. 创建线程
A.t = Thread(target=func,name='',args=(),kwargs={}) 新建状态
t.start() ---->就绪状态
run()
join()
B. 自定义线程
class MyThread(Thread):
def __init__(self,name):
super().__init__()
self.name=name
def run(self):
任务
t = MyThread('name')
t.start()
2. 数据共享
进程共享数据与线程共享数据区别:
进程是每个进程中都有一份
线程是共同一个数据 ----》 数据安全性问题
GIL ----》 伪线程
lock = Lock()
lock.acquire()
......
lock.release()
-----> 只要用锁:死锁
避免死锁
3. 线程间通信: 生产者与消费者
生产者:线程
消费者:线程
import queue
q = queue.Queue()
# 创建生产者
th = threading.Thread(target=produce, args=(q,))
th.start()
# 创建消费者
tc = threading.Thread(target=consume, args=(q,))
tc.start()
q.put()
q.get()
扩展: GIL
协程
# Process Thread 生成器完成
import time
def task1():
for i in range(3):
print('A' + str(i))
yield
time.sleep(1)
def task2():
for i in range(3):
print('B' + str(i))
yield
time.sleep(2)
if __name__ == '__main__':
g1 = task1()
g2 = task2()
while True:
try:
next(g1)
next(g2)
except:
break
# greenlet 完成协程任务
import time
from greenlet import greenlet
def a(): # 任务A
for i in range(5):
print('A' + str(i))
gb.switch()
time.sleep(0.1)
def b(): # 任务B
for i in range(5):
print('B' + str(i))
gc.switch()
time.sleep(0.1)
def c(): # 任务C
for i in range(5):
print('C' + str(i))
ga.switch()
time.sleep(0.1)
if __name__ == '__main__':
ga = greenlet(a)
gb = greenlet(b)
gc = greenlet(c)
ga.switch()
import time
import gevent
from gevent import monkey
monkey.patch_all()
def a(): # 任务A
for i in range(5):
print('A' + str(i))
time.sleep(0.1)
def b(): # 任务B
for i in range(5):
print('B' + str(i))
time.sleep(0.1)
def c(): # 任务C
for i in range(5):
print('C' + str(i))
time.sleep(0.1)
if __name__ == '__main__':
g1 = gevent.spawn(a)
g2 = gevent.spawn(b)
g3 = gevent.spawn(c)
g1.join()
g2.join()
g3.join()
print('---------------')
参考
- B站宋宋老师的教程
- python进程、线程、协程详解