当前位置: 首页 > news >正文

达州市网站建设_网站建设公司_一站式建站_seo优化

网站佣金怎么做凭证,wordpress侧边栏子栏目,wordpress博客缩略图,荣耀手机官方商城官网python多线程详解 一、线程介绍 什么是线程 线程#xff08;Thread#xff09;也叫轻量级进程#xff0c;是操作系统能够进行运算调度的最小单位#xff0c;它被包涵在进程之中#xff0c;是进程中的实际运作单位。线程自己不拥有系统资源#xff0c;只拥有一点儿在运行中…python多线程详解 一、线程介绍 什么是线程 线程Thread也叫轻量级进程是操作系统能够进行运算调度的最小单位它被包涵在进程之中是进程中的实际运作单位。线程自己不拥有系统资源只拥有一点儿在运行中必不可少的资源但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程同一进程中的多个线程之间可以并发执行。 为什么要使用多线程 线程在程序中是独立的、并发的执行流。与分隔的进程相比进程中线程之间的隔离程度要小它们共享内存、文件句柄和其他进程应有的状态。 因为线程的划分尺度小于进程使得多线程程序的并发性高。进程在执行过程中拥有独立的内存单元而多个线程共享内存从而极大地提高了程序的运行效率。 线程比进程具有更高的性能这是由于同一个进程中的线程都有共性多个线程共享同一个进程的虚拟空间。线程共享的环境包括进程代码段、进程的公有数据等利用这些共享的数据线程之间很容易实现通信。 操作系统在创建进程时必须为该进程分配独立的内存空间并分配大量的相关资源但创建线程则简单得多。因此使用多线程来实现并发比使用多进程的性能要高得多。 总结起来使用多线程编程具有如下几个优点 进程之间不能共享内存但线程之间共享内存非常容易。 操作系统在创建进程时需要为该进程重新分配系统资源但创建线程的代价则小得多。因此使用多线程来实现多任务并发执行比使用多进程的效率高。 Python 语言内置了多线程功能支持而不是单纯地作为底层操作系统的调度方式从而简化了 Python 的多线程编程。 二、线程实现 threading模块 普通创建方式 import threading import time def run(n): print(task, n) time.sleep(1) print(2s) time.sleep(1) print(1s) time.sleep(1) print(0s) time.sleep(1) if __name__ __main__: t1 threading.Thread(targetrun, args(t1,)) t2 threading.Thread(targetrun, args(t2,)) t1.start() t2.start() ----------------------------------task t1task t22s2s1s1s0s0s 自定义线程 继承threading.Thread来自定义线程类其本质是重构Thread类中的run方法 import threading import time class MyThread(threading.Thread): def __init__(self, n): super(MyThread, self).__init__() # 重构run函数必须要写 self.n n def run(self): print(task, self.n) time.sleep(1) print(2s) time.sleep(1) print(1s) time.sleep(1) print(0s) time.sleep(1) if __name__ __main__: t1 MyThread(t1) t2 MyThread(t2) t1.start() t2.start() ----------------------------------task t1task t22s2s1s1s0s0s 守护线程 我们看下面这个例子这里使用setDaemon(True)把所有的子线程都变成了主线程的守护线程因此当主进程结束后子线程也会随之结束。所以当主线程结束后整个程序就退出了。 import threading import time def run(n): print(task, n) time.sleep(1) #此时子线程停1s print(3) time.sleep(1) print(2) time.sleep(1) print(1) if __name__ __main__: t threading.Thread(targetrun, args(t1,)) t.setDaemon(True) #把子进程设置为守护线程必须在start()之前设置 t.start() print(end) ----------------------------------task t1end 我们可以发现设置守护线程之后当主线程结束时子线程也将立即结束不再执行。 主线程等待子线程结束 为了让守护线程执行结束之后主线程再结束我们可以使用join方法让主线程等待子线程执行。 import threading import time def run(n): print(task, n) time.sleep(1) #此时子线程停1s print(3) time.sleep(1) print(2) time.sleep(1) print(1) if __name__ __main__: t threading.Thread(targetrun, args(t1,)) t.setDaemon(True) #把子进程设置为守护线程必须在start()之前设置 t.start() t.join() # 设置主线程等待子线程结束 print(end) ----------------------------------task t1321end 多线程共享全局变量 线程是进程的执行单元进程是系统分配资源的最小单位所以在同一个进程中的多线程是共享资源的。 import threading import time g_num 100 def work1(): global g_num for i in range(3): g_num 1 print(in work1 g_num is : %d % g_num) def work2(): global g_num print(in work2 g_num is : %d % g_num) if __name__ __main__: t1 threading.Thread(targetwork1) t1.start() time.sleep(1) t2 threading.Thread(targetwork2) t2.start() ----------------------------------in work1 g_num is : 103in work2 g_num is : 103 互斥锁 由于线程之间是进行随机调度并且每个线程可能只执行n条执行之后当多个线程同时修改同一条数据时可能会出现脏数据所以出现了线程锁即同一时刻允许一个线程执行操作。线程锁用于锁定资源你可以定义多个锁, 像下面的代码, 当你需要独占某一资源时任何一个锁都可以锁这个资源就好比你用不同的锁都可以把相同的一个门锁住是一个道理。 由于线程之间是进行随机调度如果有多个线程同时操作一个对象如果没有很好地保护该对象会造成程序结果的不可预期我们也称此为“线程不安全”。 为了方式上面情况的发生就出现了互斥锁(Lock) from threading import Thread,Lock import os,time def work(): global n lock.acquire() tempn time.sleep(0.1) ntemp-1 lock.release() if __name__ __main__: lockLock() n100 l[] for i in range(100): pThread(targetwork) l.append(p) p.start() for p in l: p.join() 递归锁 RLcok类的用法和Lock类一模一样但它支持嵌套在多个锁没有释放的时候一般会使用RLcok类。 import threading import time def Func(lock): global gl_num lock.acquire() gl_num 1 time.sleep(1) print(gl_num) lock.release() if __name__ __main__: gl_num 0 lock threading.RLock() for i in range(10): t threading.Thread(targetFunc, args(lock,)) t.start() 信号量BoundedSemaphore类) 互斥锁同时只允许一个线程更改数据而Semaphore是同时允许一定数量的线程更改数据 比如厕所有3个坑那最多只允许3个人上厕所后面的人只能等里面有人出来了才能再进去。 import threading import time def run(n, semaphore): semaphore.acquire() #加锁 time.sleep(1) print(run the thread:%s\n % n) semaphore.release() #释放 if __name__ __main__: num 0 semaphore threading.BoundedSemaphore(5) # 最多允许5个线程同时运行 for i in range(22): t threading.Thread(targetrun, args(t-%s % i, semaphore)) t.start() while threading.active_count() ! 1: pass # print threading.active_count() else: print(-----all threads done-----) 事件Event类 python线程的事件用于主线程控制其他线程的执行事件是一个简单的线程同步对象其主要提供以下几个方法 clear将flag设置为“False” set将flag设置为“True” is_set判断是否设置了flag wait会一直监听flag如果没有检测到flag就一直处于阻塞状态 事件处理的机制全局定义了一个“Flag”当flag值为“False”那么event.wait()就会阻塞当flag值为“True”那么event.wait()便不再阻塞。 #利用Event类模拟红绿灯 import threading import time event threading.Event() def lighter(): count 0 event.set() #初始值为绿灯 while True: if 5 count 10 : event.clear() # 红灯清除标志位 print(\33[41;1mred light is on...\033[0m) elif count 10: event.set() # 绿灯设置标志位 count 0 else: print(\33[42;1mgreen light is on...\033[0m) time.sleep(1) count 1 def car(name): while True: if event.is_set(): #判断是否设置了标志位 print([%s] running...%name) time.sleep(1) else: print([%s] sees red light,waiting...%name) event.wait() print([%s] green light is on,start going...%name) light threading.Thread(targetlighter,) light.start() car threading.Thread(targetcar,args(MINI,)) car.start() 三、GILGlobal Interpreter Lock全局解释器锁 在非python环境中单核情况下同时只能有一个任务执行。多核时可以支持多个线程同时执行。但是在python中无论有多少核同时只能执行一个线程。究其原因这就是由于GIL的存在导致的。 GIL的全称是Global Interpreter Lock(全局解释器锁)来源是python设计之初的考虑为了数据安全所做的决定。某个线程想要执行必须先拿到GIL我们可以把GIL看作是“通行证”并且在一个python进程中GIL只有一个。拿不到通行证的线程就不允许进入CPU执行。GIL只在cpython中才有因为cpython调用的是c语言的原生线程所以他不能直接操作cpu只能利用GIL保证同一时间只能有一个线程拿到数据。而在pypy和jpython中是没有GIL的。 Python多线程的工作过程 python在使用多线程的时候调用的是c语言的原生线程。 拿到公共数据 申请gil python解释器调用os原生线程 os操作cpu执行运算 当该线程执行时间到后无论运算是否已经执行完gil都被要求释放 进而由其他进程重复上面的过程 等其他进程执行完后又会切换到之前的线程从他记录的上下文继续执行整个过程是每个线程执行自己的运算当执行时间到就进行切换context switch。 python针对不同类型的代码执行效率也是不同的 1、CPU密集型代码(各种循环处理、计算等等)在这种情况下由于计算工作多ticks计数很快就会达到阈值然后触发GIL的释放与再竞争多个线程来回切换当然是需要消耗资源的所以python下的多线程对CPU密集型代码并不友好。 2、IO密集型代码(文件处理、网络爬虫等涉及文件读写的操作)多线程能够有效提升效率(单线程下有IO操作会进行IO等待造成不必要的时间浪费而开启多线程能在线程A等待时自动切换到线程B可以不浪费CPU的资源从而能提升程序执行效率)。所以python的多线程对IO密集型代码比较友好。 使用建议 python下想要充分利用多核CPU就用多进程。因为每个进程有各自独立的GIL互不干扰这样就可以真正意义上的并行执行在python中多进程的执行效率优于多线程(仅仅针对多核CPU而言)。 GIL在python中的版本差异 1、在python2.x里GIL的释放逻辑是当前线程遇见IO操作或者ticks计数达到100时进行释放。ticks可以看作是python自身的一个计数器专门做用于GIL每次释放后归零这个计数可以通过sys.setcheckinterval 来调整。而每次释放GIL锁线程进行锁竞争、切换线程会消耗资源。并且由于GIL锁存在python里一个进程永远只能同时执行一个线程(拿到GIL的线程才能执行)这就是为什么在多核CPU上python的多线程效率并不高。 2、在python3.x中GIL不使用ticks计数改为使用计时器执行时间达到阈值后当前线程释放GIL这样对CPU密集型程序更加友好但依然没有解决GIL导致的同一时间只能执行一个线程的问题所以效率依然不尽如人意。
http://www.ihoyoo.com/news/122166.html

相关文章:

  • 诸暨哪些公司可以制作网站南通建设厅网站
  • 济南网站建设哪家便宜主机屋wordpress
  • 西安网站建设收费标准在线答题网站怎么做
  • 网站文字设计怎么在自己电脑做网站
  • 宁波网站建设lonoo网站建设需求方案
  • kuake自助建站系统源码福建省网站建设公司
  • 西安做网站一般多少钱东莞网站竞价推广
  • 专业网站制作哪家专业电子商务网站系统开发
  • 怎么申请一个网站做网站需要的相关知识
  • 盐城网站建设哪家快网站的排版包括什么
  • 网站数据分离 怎么做到哪里学平面设计
  • 网站建设花都上海建筑工程网
  • 做a货包好的网站格拉苏蒂手表网站
  • ckplarer整合wordpress天津seo结算
  • 移动应用开发和网站开发怎样做好手机网站建设
  • 交通建设网站网页制作工具有哪些
  • 多媒体网站开发实战下载app到手机上并安装
  • 长沙大型网站设计公司seosem推广
  • 低价代网站滁州房地产网站建设网站
  • 西安网站建设服务标题优化怎样选关键词
  • 常州武进建设局网站网站建设注册什么公司好
  • 个人网站建设报告企业网站建设制作多少钱
  • 集团门户网站建设方案 php网站做留言板
  • 黄页营销网站山东微道商网络技术有限公司
  • 建手机网站的平台深圳网页设计公司排行
  • 微网站功能介绍赣州新闻视频
  • 建设教育局网站硬件价格需要多少钱vs210做网站
  • 同城手机网站开发html代码大全简单
  • 如何在腾讯云做网站网络营销外包要多少钱
  • 南阳网站建设培训班苏州外贸网站制作公司