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

[经验分享] python线程开发

[复制链接]
YunVN网友  发表于 2018-8-16 06:15:08 |阅读模式
  线程(有时被称为轻量级进程)跟进程有些相似,不同的是所有的线程运行在同一个进程中,共享相同的运行环境。它们可以想像成是在主进程或“主线程”中并行运行的“迷你进程”。线程有开始、顺序执行和结束三部分,它有一个自己的指令指针,记录自己运行到什么地方。线程的运行可能被抢占(中断)或暂时的被挂起(也叫睡眠)让其它的线程运行,这叫做让步。一个进程中的各个线程之间共享同一片数据空间,所以线程之间可以比进程之间更方便地共享数据以及相互通讯。线程一般都是并发执行的,正是由于这种并行和数据共享的机制使得多个任务的合作变为可能。实际上,在单CPU的系统中,真正的并发是不可能的,每个线程会被安排成每次只运行一小会,然后就把CPU让出来,让其它的线程去运行。在进程的整个运行过程中,每个线程都只做自己的事,在需要的时候跟其它的线程共享运行的结果。多个线程共同访问同一片数据不是完全没有危险的,由于数据访问的顺序不一样,有可能导致数据结果的不一致的问题,这叫做竞态条件。而大多数线程库都带有一系列的同步原语,来控制线程的执行和数据的访问。
  Python全局锁
  Python代码的执行由Python虚拟机(也叫解释器主循环)来控制。Python在设计之初就考虑到要在主循环中,同时只有一个线程在执行。虽然 Python 解释器中可以“运行”多个线程,但在任意时刻只有一个线程在解释器中运行。
  对Python虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同一时刻只有一个线程在运行。在多线程环境中,Python 虚拟机按以下方式执行:a、设置 GIL;b、切换到一个线程去运行;c、运行指定数量的字节码指令或者线程主动让出控制(可以调用 time.sleep(0));d、把线程设置为睡眠状态;e、解锁 GIL;d、再次重复以上所有步骤。
  任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。
  例子:
  1、
  import threading
  import time
  def haha(max_num):
  for i in range(max_num):
  time.sleep(1)
  print i
  for x in range(3):
  """
  这里的rang(3)是要依次启动三个线程,每个线程都调用函数haha()
  第一个线程启动执行之后,马上启动第二个线程再次执行。最后也相当于
  函数执行了3次
  """
  #通过threading.Thread方法实例化多线程类
  #target后面跟的是函数的名称但是不要带括号也不填写参数
  #args后面的内容才是要传递给函数haha()的参数。切记参数一定要以元组的形式填写不然会报错。
  t=threading.Thread(target=haha,args=(10,))
  #将线程设置为守护线程
  t.setDaemon(True)
  #线程准备就绪,随时等候cpu调度
  t.start()
  setDaemon()
  如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止
  如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止
  2、.join()的用法
  import threading
  import time
  def haha(max_num):
  for i in range(max_num):
  time.sleep(1)
  print i
  """
  创建一个列表,用于存储要启动多线程的实例
  """
  threads=[]
  for x in range(3):
  t=threading.Thread(target=haha,args=(5,))
  #把多线程的实例追加入列表,要启动几个线程就追加几个实例
  threads.append(t)
  for thr in threads:
  #把列表中的实例遍历出来后,调用start()方法以线程启动运行
  thr.start()
  for thr in threads:
  """
  isAlive()方法可以返回True或False,用来判断是否还有没有运行结束
  的线程。如果有的话就让主线程等待线程结束之后最后再结束。
  """
  if thr.isAlive():
  thr.join()
  程序运行的时候最先启动的一定就是主线程,主线程负责拉起子线程用于干活。我们的例子中运行函数haha()线程其实都是子线程。因此可以说多线程其实就是多个子线程。那么程序运行完最后一个退出的也肯定就是主线程。因此上例中最后再遍历一个遍threads列表的目的就是查看还是否有没有退出的子线程,只要还有子线程是活的,没有退出。就通过join()方法强制程序流程不可以走到主线程退出的那个步骤。只有等子线程都退出之后,才能根据join()方法的规则顺序执行到主线程退出的步骤。
  3、通过类来实现线程
  import threading
  import time
  class haha(threading.Thread):
  """
  自定义一个类haha,必须要继承threading.Thread,下面必须要重写一个run()方法。
  把要执行的函数写到run()方法里。如果没有run()方法就会报错。其实这个类的作用就是
  通过haha类里面的run()方法来定义每个启动的子线程要执行的函数内容。
  """
  def __init__(self,max_num):
  threading.Thread.__init__(self)
  self.max_num=max_num
  def run(self):
  for i in range(self.max_num):
  time.sleep(1)
  print i
  if __name__==‘__main__‘:
  threads=[]
  for x in range(3):
  """
  只是这里和函数方式有点区别,因为haha类继承了threading.Thread,所以通过haha类的实例化
  就相当于调用了多线程的实例化。剩下的操作就和函数方式一个样子了。
  """
  t=haha(5)
  threads.append(t)
  for thr in threads:
  thr.start()
  for thr in threads:
  if thr.isAlive():
  thr.join()
  4、线程锁
  import threading
  gnum=0
  lock=threading.RLock()
  def work(max_number):
  for i in range(max_number):
  print i
  def mylock():
  work(10)
  #在操作gnum之前先上锁
  #acquire()的括号里可以定义锁定的timeout时间,超过这个时间就自动打开锁
  lock.acquire()
  global gnum
  gnum=gnum+1
  #操作结束之后再打开锁
  lock.release()
  print ‘gnum is ‘,gnum
  for x in range(5):
  t=threading.Thread(target=mylock)
  t.start()
  什么是线程锁呢?就是在多个线程同时操作一个资源的时候,哪个线程先操作。哪个线程就先锁定这个资源。直到这个线程操作结束打开锁之后,其他的线程才能再操作。这就叫做线程安全,也就是线程锁,上例子如果不加线程锁,得到的gnum的结果会得不到预期,线程操作是同时的,多个线程操作同一个数据。

运维网声明 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-552333-1-1.html 上篇帖子: python文件打开和关闭 第四篇 下篇帖子: python 网络编程 第六篇
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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