设为首页 收藏本站
查看: 1295|回复: 0

[经验分享] python程序默认执行与多线程

[复制链接]

尚未签到

发表于 2018-8-4 10:35:17 | 显示全部楼层 |阅读模式
一、程序执行流程和进程线程简述
  1程序执行流程
  有类似脚本程序或编程经验的同学都知道,程序默认是自上而下,从左到右的按顺序执行,也叫串行执行;而多线程类似于并行执行,即A模块(函数)执行时B也执行不需要等A执行完再执行,这里请区别对待并发执行(同一时间执行);以上是简单概念性描述,
  2什么是线程与进程?
  线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务
  本节不讨论进程.以下主要说明线程的应用.进程,以及进程与线程,有兴趣可以参考这里
  3python中的线程
  以下引用廖雪峰博客Python的线程虽然是真正的线程,但解释器执行代码时,有一个GIL锁:Global Interpreter Lock,任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。后面通过示例说明这一点.
  

     GIL是Python解释器设计的历史遗留问题,通常我们用的解释器是官方实现的CPython,要真正利用多核,除非重写一个不带GIL的解释器。  

  所以,在Python中,可以使用多线程,但不要指望能有效利用多核。如果一定要通过多线程利用多核,那只能通过C扩展来实现,不过这样就失去了Python简单易用的特点。
  不过,也不用过于担心,Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。多个Python进程有各自独立的GIL锁,互不影响.

二、python程序执行流程示例
  以下示例均在python3.5.2中完成
  1、默认执行流程
  

import time  

  
def Foo():
  sleep(2)
  print("I am Foo.")
  

  
def Bar():
  sleep(3)
  print("I am Bar.")
  

  
if __name__ == "__main__":
  start = time.time()  #程序执行开始时间
  Foo()
  Bar()
  end = time.time()
  print("程序执行完使用 %s" %(end - start))
  

  

  执行结果:
DSC0000.jpg

  可以看出,程序从上而下的调用了Foo函数休眠2秒再执行Bar函数休眠3秒,最后执行完成共使用大约5秒多一点时间.这说明 Foo执行完才执行Bar.
  2、线程执行
  在讨论线程时,先问一个问题,自上而下的串行执行可以满足条件,为啥要多线程并行去执行?想像一个场景,我们在看一部电影时,要是默认串行执行,先放图像 再放电影中的声音,能接受吗?
  

def Movie_music(func):  print(threading.current_thread())
  for i in range(2):
  print("Begin  listening to %s . %s" %(func,ctime()))
  sleep(2)
  print("End listening %s" % ctime())
  

  
def Movie_grap(func):
  print(threading.current_thread())
  for i in range(2):
  print("Begin watching at the %s! %s" %(func,ctime()))
  sleep(3)
  print("End watching %s" %ctime())
  

  
threads= []
  
t1 = threading.Thread(target=Movie_music,args=(u"七里香.mtv",))
  
threads.append(t1)
  
t2 = threading.Thread(target=Movie_grap,args=(u"七里香.mtv",))
  
threads.append(t2)
  

  
if __name__ == "__main__":
  for t in threads:
  

  t.start()
  t.join()
  print("MTV播放结束: %s" %ctime())
  

  执行结果:
DSC0001.jpg

  所谓的多线程并不是同一时刻而是在很多的时间内进行了切换,而人的感观只要超过1/12之秒基本等同于同一时间,从上面的started 140049239336704 可以看出纳秒级别,时间上基本是同一秒,所以这首MTV中的音乐和图像 让我感觉 是同时发生的.这就是多线程的好处.如果换成串行播放,那一个五分钟的MTV可能就要10分钟播放完,先放声音或先放图像.

三、什么时候使用python中的多线程
  

    由于python解释器执行代码时,有一个GIL锁:Global Interpreter Lock的限制,多线程在Python中只能交替执行,即使100个线程跑在拥有100核CPU上,也只能用到1个核。其他核无法在多线程情况下使用.  

  计算密集型操作之串行
  

import time  
def add(n):
  sum = 0
  for i in range(int(n)):
  sum+=i
  print(sum)
  print("finshed.")
  

  
if __name__ == "__main__":
  start = time.time()
  add(100000000)
  add(10000000)
  end = time.time()
  print(end - start)
  

  运行结果:
DSC0002.jpg

  计算密集型操作之多线程并行执行
  

def add(n):  sum = 0
  for i in range(int(n)):
  sum+=i
  print(sum)
  print("finshed.")
  

  
if __name__ == "__main__":
  start = time.time()
  t1 = threading.Thread(target=add,args=(100000000,))  #计算密集型
  t1.start()
  

  t2 = threading.Thread(target=add, args=(10000000,))
  t2.start()
  

  t1.join()
  t2.join()
  

  end = time.time()
  print(end - start)
  

  运行结果:
DSC0003.jpg

  可以看出无论是串行执行还是多线程并行执行,计算结果一样,但花费的时间多线程并没有少于串行执行,反而略多,在python2.x上差距会更多,而上面的例子是IO密集型多线程明显要优于串行.
  所以对于IO密集型情况使用多线程比较合适,而对于计算密集型由于python GIL的限制不能真正使用多核,无法提高cpu计算效率,不宜使用多线程.可以采用多进程多线程方式 .

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-546346-1-1.html 上篇帖子: 【Python之旅】第五篇(三):Python Socket多线程并发 下篇帖子: Python的最大递归深度错误 “maximum recursion depth exceeded while calling a Python object”
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表