python中线程和协程
1 线程
Python实现线程,使用threading模块实现。start方法是启动线程;join方法是等待当前线程。
import threading
import time
import random
# 线程A
def thread_a():
for i in range(3):
print("线程A--%d" % i)
# 随机睡眠1-4秒
time.sleep(random.randint(1, 4))
# 线程B
def thread_b():
for i in range(3):
print("线程B--%d" % i)
time.sleep(random.randint(1, 4))
if __name__ == '__main__':
# 参数target是线程执行的函数名
my_thread_a = threading.Thread(target=thread_a)
my_thread_b = threading.Thread(target=thread_b)
# 启动线程A
my_thread_a.start()
# 等待my_thread_a执行完成后,再继续执行
# my_thread_a.join()
# 启动线程B
my_thread_b.start()
print("主线程")
2 协程
由于python受到全局解释器锁(Global Interpreter Lock, GIL)的限制,任何时候只能有一个thread处于运行状态。因此,python的单线程和多线程的运行效果相差不大。因此,推荐使用协程解决并发问题。
协程(Coroutine)是单线程下的并发,又称微线程,纤程。它是一种用户态的轻量级线程,即是由用户程序自己控制调度的。
实现协程有yield(yield是python自带的手动切换协程的模块)、 greenlet(greenlet是基于C实现的半自动切换协程的模块)、gevent(gevent是基于greenlet实现的自动切换协程的模块)三种方法实现协程。此处主要使用gevent实现协程。
实现协程之间的锁,可以使用 BoundedSemaphore,可以使用 acquire、 release方法实现锁。
# 安装gevent
# pip install gevent
import gevent
from gevent import monkey
import time
import random
# 必须添加“猴子补丁”,否则不能自动切换协程
monkey.patch_all()
def gevent_a(n):
for i in range(n):
print("协程A--%d" % i)
time.sleep(random.randint(1, 4))
def gevent_b(n):
for i in range(n):
print("协程B--%d" % i)
# time.sleep(random.randint(1, 4))
if __name__ == '__main__':
# 创建协程对象
my_gevent_a = gevent.spawn(gevent_a, 4)
my_gevent_a.run()
my_gevent_b = gevent.spawn(gevent_b, 4)
my_gevent_b.run()
# 阻塞主线程,等待协程。此处需要阻塞主线程,等待协程
my_gevent_a.join()
my_gevent_b.join()
print("主线程")