1、python的多线程

多线程就是在同一时刻执行多个不同的程序,然而python中的多线程并不能真正的实现并行,这是由于cpython解释器中的GIL(全局解释器锁)捣的鬼,这把锁保证了同一时刻只有一个线程被执行。

多线程的特点:

线程比进程更轻量级,创建一个线程要比创建一个进程快10-100倍。

线程共享全局变量。

由于GIL的原因,当一个线程遇到IO操作时,会切换到另一个线程,所以线程适合IO密集型操作。

在多核cpu系统中,最大限度的利用多核,可以开启多个线程,开销比进程小的多,但是这并不适合python。

多线程互斥锁:

因为线程共享全局变量,所以需要互斥锁去限制线程对全局变量的更改。

假设,当一个线程在执行到获取全局变量的时候,这个后GIL切换到另一个线程执行,这个时候新的线程为全局变量+1后切换回之前的线程,之前的线程中的全局变量还是+1前的值,所以需要互斥锁。

为什么有了GIL锁还要互斥锁呢?

GIL锁只是控制同一时刻下只有一个线程被执行,这并不能控制同一时刻只有一个线程去获取并更改全局变量,所以需要使用互斥锁。

多线程的实现:

#导入threading模块

importthreading#定义全局变量

i=0#定义互斥锁

mutex =threading.Lock()defa():#申明全局变量i

globalifor j in range(2000000):#获取互斥锁

mutex.acquire()

i+=1

#释放互斥锁

mutex.release()defb():globalifor j in range(2000000):

mutex.acquire()

i+=1mutex.release()#创建线程

t1 = threading.Thread(target=a)

t2= threading.Thread(target=b)#开启线程

t1.start()

t2.start()#等待所有线程结束

t1.join()

t2.join()print(i)

2、python中的多进程

python的多线程不能利用多核的优势,如果想要充分的利用多核cpu的资源,python中大部分情况需要使用多进程。

python多进程的特点:

进程间不共享全局变量,进程修改的数据仅限于该进程内。

进程创建和销毁的开销比较大。

相对于线程,进程更适合与计算密集型操作。

能充分利用多核的优势。

进程间通信:

既然进程间中不公共享全局变量,那么多进程间怎么进行通信呢?可以使用multiprocessing中的Queue模块,当然也可以使用socket、管道、共享内存等方式。

多进程的实现:

#导入multiprocessin模块

importmultiprocessing#创建队列

queue =multiprocessing.Queue()#定义全局变量

a =0#定义函数

defwork1(num):#获取队列中的数据,如果没有数据,将堵塞

a =queue.get()#将队列中的数据+2000000次num

for i in range(2000000):

a+=num#将数据存放在队列中

queue.put(a)#打印最终结果

print("work1",a)#定义函数

defwork2():#申明全局变量a

globala#将a+2000000次1

for i in range(2000000):

a+=1

#打印最总结果

print("work2",a)#将a存放在队列中

queue.put(a)#创建进程

p1 = multiprocessing.Process(target=work1, args=(2,))

p2= multiprocessing.Process(target=work2)#启动进程

p1.start()

p2.start()#等待进程结束

p1.join()

p2.join()#获取队列中的数据

a =queue.get()#打印a

print(a)

进程池的实现

进程池能减少重复创建和销毁进程的开销问题

#导入需要的模块

importmultiprocessingimporttimeimportrandom#定义函数

defwork(num):print("num=",num)

time.sleep(random.randint(0,2))#创建进程池,设置进程的数量

pool = multiprocessing.Pool(3)for i in range(10):#开启进程

pool.apply_async(work, args=(i,))#设置等待时间,等待所有进程结束

time.sleep(20)

3、python中的协程

在linux中线程就是轻量级的进程,而我们通常也把协程称为轻量级的线程。

对比进程和协程:

进程是内核调度,而协程是在用户态调度,所以说进程的上下文在内核态保存恢复,而协程是在用户态保存恢复的,所以协程的开销比进程低。

进程会被抢占,而协程不会,也就是说协程如果不主动让出cpu,那么其他的协程就没有执行的机会。

进程所需要的内存比协程大得多

对比线程和协程:

线程的上下文切换成本相对于协程来说比较高。

线程的切换由操作系统来控制,而协程的切换由我们自己控制。

yield实现协程:

#定义两个函数

defwork1():whileTrue:print("work1")#当程序运行到yield就会暂停,等待下次的next调用,然后继续执行

yield

defwork2():whileTrue:print("work2")yieldw1=work1()

w2=work2()whileTrue:#使用next函数启动

next(w1)

next(w2)

greenlet实现协程:

greenlet安装:

sudo pip3 install greenlet

code:

#导入greenlet模块

from greenlet importgreenletdefwork1():for i in range(10):print("work1")#打印过后跳转至协程g2继续执行

g2.switch()defwork2():for i in range(10):print("work2")#打印后跳转至协程g1继续执行

g1.switch()#创建协程g1

g1 =greenlet(work1)#创建协程g2

g2 =greenlet(work2)#跳转至协程g1

g1.switch()

gevent实现协程:

gevent是基于greenlet的并发网络库,每当有一个协程堵塞的时,程序将自动调度。

monkey-patching:

一般称为猴子补丁,这个补丁能直接修改标准库里面大部分的阻塞式系统调用。但是如果在复杂的生产环境中使用了这些标准库,可能就会因为打了补丁而出现奇怪的问题。

gevent安装:

sudo pip3 install gevent

code:

#导入所需要的模块

importgeventimporttimefrom gevent importmonkey#猴子补丁,monkey.patch_all()方法将所有的标准库都替换掉#使用猴子补丁褒贬不一,但是官网上还是建议使用patch_all(),而且在程序的第一行就执行

monkey.patch_all()deff(n):for i inrange(n):print(i)#设置延时

time.sleep(0.5)#如果没有导入monkey模块的话,需要使用gevent.sleep()

#gevent.sleep(0.5)

#----------------写法一--------------------#创建greenlet协程对象#g1 = gevent.spawn(f,5)#g2 = gevent.spawn(f,5)#g3 = gevent.spawn(f,5)#等待所有greenlet携程结束后退出#g1.join()#g2.join()#g3.join()

#----------------写法二--------------------

gevent.joinall([gevent.spawn(f,5), gevent.spawn(f,5), gevent.spawn(f,5)])

python多线程多进程多协程_python 多进程、多线程、协程相关推荐

  1. python从网址爬图片协程_python 用 gevent 协程抓取海量网页

    python作为爬虫利器,抓网页的方式简洁明了.爬成百上千的网页,都可以很快爬完,但是如果网页数量上万呢?速度就不能忍受了. 这是一段爬取页面的函数,用了requests库:1 2 3 4 5impo ...

  2. python多进程运行死机_python多进程假死

    结论:python多进程间用Queue通信时,如果子进程操作Queue满了或者内容比较大的情况下,该子进程会阻塞等待取走Queue内容(如果Queue数据量比较少,不会等待),如果调用join,主进程 ...

  3. python多进程爬虫保存数据_Python多进程爬虫东方财富盘口异动数据+Python读写Mysql与Pandas读写Mysql效率对比...

    先上个图看下网页版数据.mysql结构化数据 通过Python读写mysql执行时间为:1477s,而通过Pandas读写mysql执行时间为:47s,方法2速度几乎是方法1的30倍.在于IO读写上, ...

  4. python编写下载器可暂停_python多进程断点续传分片下载器

    python多进程断点续传分片下载器 标签:python 下载器 多进程 因为爬虫要用到下载器,但是直接用urllib下载很慢,所以找了很久终于找到一个让我欣喜的下载器.他能够断点续传分片下载,极大提 ...

  5. python多进程读同一个文件_python 多进程读写文件

    import time from multiprocessing import Process, JoinableQueue, cpu_count import csv ####处理一条数据的方法 d ...

  6. python多进程用不了_Python多进程相关的坑

    Python的multiprocessing模块实现了多进程功能,但官方文档上只有一些比较简单的用法,主要是使用函数作为process的target,而如何在class中使用多进程并没有多讲解.goo ...

  7. python从网址爬图片协程_Python爬虫多任务协程爬取虎牙MM图片

    查看: 4420|回复: 241 [作品展示] Python爬虫多任务协程爬取虎牙MM图片 电梯直达 发表于 2019-4-17 21:35:47 | 只看该作者 |倒序浏览 |阅读模式 马上注册,结 ...

  8. python函数可以提高运行效率吗_python 多进程如何提高函数效率?

    1 如何利用multiprocessing 库提高单个函数的执行效率 2 代码如下: def f(): urls = ['http://yanbao.stock.hexun.com/listnews1 ...

  9. python多进程加快for循环_python多进程 通过for循环 join 的问题

    代码如下: importos frommultiprocessing importProcess deffunc(num):print('in func',num,os.getpid(),os.get ...

最新文章

  1. python文本操作
  2. 敏捷个人俱乐部2012年2月线下活动:活出我的最好生活
  3. 异步的两种写法: async 与 BeginInvoke
  4. zookeeper源码分析之五服务端(集群leader)处理请求流程
  5. lync 安装后相关防病毒软件的设置
  6. c语言二极管控制程序,二极管(STC89C52): 编写程序控制二极管花样流水灯
  7. SAS 中计算总和或者计算总数的方法
  8. Django之创建应用以及配置路由
  9. JS——offsetWidth与offsetLeft用法之无缝滚动
  10. 使用R的金融统计:收益、随机行走和模拟
  11. 超级好看的windows终端美化教程
  12. jq-ui-multiselect插件的使用
  13. java获取本机的ip地址
  14. HTML5:<abbr>元素
  15. 云上架构和传统IT架构的区别在哪里?(企业CIO、CTO必读)
  16. 网络架构采用 bs/cs 混搭模式_深扒英伟达安培新架构,五大技术新招刀刀见血...
  17. OpenCV之图像的载入、显示与输出
  18. 关于学习渲染的心得第一篇
  19. 【11年华科计算机考研经验】追梦华中大-我的漫漫考研路
  20. 网络基础之BGP(边界网关协议)

热门文章

  1. angularJS前台传list数组,后台springMVC接收数组
  2. PADS 创建封装笔记
  3. myeclipse同时部署两个项目-permgen space
  4. 【求解】未定义的析构函数
  5. EOS账户系统(1)场景
  6. 比特币钱包(2) BIP32 HD钱包之生成子密钥
  7. C++ Primer 5th笔记(10)chapter10 泛型算法 :write
  8. union一个有趣的应用
  9. Opencv轻松入门:OpenCV入门难?资料少?看完这篇文章就稳了
  10. optee中spinlock的实现原理详解