python中协程和线程的区别,python线程和协程区别
并发编程是实现多任务协同处理、提高系统性能的一种方式。在Python中实现并发编程主要依靠进程、线程和协程。本文将通过实例说明其中的区别,有兴趣的可以看看。
00-1010 1.什么是并发编程2。过程和多重过程3。线程和多线程4。协进程和多进程。摘要
目录
并发编程是实现多任务协同处理、提高系统性能的一种方式。在Python中实现并发编程主要依赖于
进程:进程是程序在计算机中关于一个数据集的运行实例,是操作系统分配资源的最小单位。
线程:线程包含在一个进程中,是操作系统调度和执行程序的最小单位。
协程:协程是在用户模式下执行的轻量级编程模型,由单线程调度。
直接看上图三个概念的关系。
这张图说明了什么?首先,线程是进程中的单个顺序控制流,一个进程可以由多个线程并发执行不同的任务。该进程由发出控制信号的单线程调度,而不是由操作系统管理,因此该进程没有切换开销和同步锁定机制,具有非常高的执行效率。
进程、线程和协同程序之间的特性决定了它们不同的应用场景:
协同处理通常用于IO密集型工作,如网络资源请求等。进程和线程经常用于计算密集型工作,如科学计算、人工神经网络等。
接下来,详细描述每种并发编程方法。
1.什么是并发编程
Python多进程依赖于标准库mutiprocessing,进程类进程的常用方法如下
方法含义1start()创建一个流程子流程实例,并执行该实例的run()方法。2run()子流程需要执行的目标任务。3join()主流程阻塞并等待子流程继续执行,直到子流程完成。可以设置超时timeout4terminate()终止子流程5is_alive()来判断子流程是否终止。6daemon设置子进程是否与主进程一起退出。创建多进程任务的示例如下
导入操作系统,时间
导入多重处理
类myProcess(多重处理。流程):
def __init__(self,*args,**kwargs) - None:
超级()。__init__()
self.name=kwargs[name]
定义运行(自身):
打印(进程名: ,自身名)
对于范围(10):内的I
print(multi processing . current _ process(), process pid: ,
Os.getpid(),正在执行.)
时间.睡眠(0.2)
if __name__==__main__:
task=my process(name= test process )
task.start()
Task.join()#该语句阻塞主进程,直到子进程结束。
打印(-)
注意:子进程结束后,Windows系统会立即自动清除子进程实例;而Linux系统的子进程实例只有在主进程结束后才会被回收,在子进程结束但主进程还在运行的这段时间里,它会处于僵尸进程状态,会造成性能损失甚至死锁。子流程实例的手动回收可以通过
p .终止()
连接()
完成了。此外,start()函数还具有清除僵尸进程的功能。使用多进程处理任务时,进程越多越好,因为进程切换会造成性能开销。
">
3.线程与多线程
Python多线程依赖于标准库threading,线程类Thread的常用方法如下表:
关于线程与进程的关系,还有一个很生动的例子
把一条公路看作一道进程,那么公路上的各个车道就是进程中的各个线程。这些线程(车道)共享了进程(道路)的公共资源;这些线程(车道)之间可以并发执行(各个车道相对独立),也可以互相同步(交通信号灯)。
rsrc = 10lock = threading.Lock()
def task1(name):
global rsrc, lock
for i in range(5):
with lock:
rsrc += 1
print("task1:", rsrc)
return name + "has been done!"
def task2(name):
global rsrc, lock
for i in range(5):
lock.acquire()
rsrc -= 1
print("task2:", rsrc)
lock.release()
return name + "has been done!"
结果如下
在多线程并发过程中,若没有控制好线程间的执行逻辑,将可能产生死锁现象,可以使用with关键词在线程访问临界区结束后自动释放锁,也可使用release()方法手动释放句柄。
4.协程与多协程
协程适用于I/O密集型而非计算密集型场景。在协程发起I/O请求后返回结果前往往有大量闲置时间——该时间可能用于网络数据传输、获取协议头、服务器查询数据库等,而I/O请求本身并不耗时,因此协程可以发送一个请求后让渡给系统干别的事,这就是协程提高性能的原因。
协程编程的框架如下:
- 创建协程对象并将其封装成任务实例;
- 创建事件循环实例并监听任务队列;
- 获取协程结果(可在事件循环结束后获取,或提前添加回调函数)。
一个嵌套协程的示例如下:
import asyncio, time# 内层协程
async def do_some_work(x):
print(Waiting: , x)
await asyncio.sleep(x)
return Done after {}s.format(x)
def OnCallBack(res):
print(res.result())
# 外层协程main
async def main():
# 创建三个协程对象并封装成任务
task1 = asyncio.ensure_future(do_some_work(1))
task2 = asyncio.ensure_future(do_some_work(8))
task3 = asyncio.ensure_future(do_some_work(4))
# 添加回调
task1.add_done_callback(OnCallBack)
task2.add_done_callback(OnCallBack)
task3.add_done_callback(OnCallBack)
# 内层任务列表
tasks = [task1, task2, task3]
# 将列表转为可等待对象
dones, pendings = await asyncio.wait(tasks)
# 外层协程func
async def func():
for i in range(5):
print("func:", i)
# 外层任务列表
tasks = [asyncio.ensure_future(func()), asyncio.ensure_future(main())]
# 创建事件循环
loop = asyncio.get_event_loop()
start = time.time()
# 监听异步任务
loop.run_until_complete(asyncio.wait(tasks))
end = time.time()
print("总耗时:", end - start)
5.总结
看了这么多概念可能有点晕了,下面这张表总结了本文的内容。总得来说,进程、线程、协程各有各的应用场景,不能说多进程、多线程、多协程就一定好,而是要根据具体的使用情况来确定。
到此这篇关于一文搞懂Python中的进程,线程和协程的文章就介绍到这了,更多相关Python进程 线程 协程内容请搜索盛行IT软件开发工作室以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT软件开发工作室!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。