赞
踩
进程实际上是不干活的,线程才是干活的那一位
进程既可以并发,也可以并行
线程只能并发,不能并行
同一时间,一个进程中的多条线程只能被一个CPU执行
#python中的线程可以并发,但是不能并行(同一个进程下的多个线程不能分开被多个cpu同时执行)
#原因:
全局解释器锁(Cpython解释器特有) GIL锁:
同一时间,一个进程下的多个线程只能有一个被cpu执行,不能实现线程的并行操作
python是解释型语言,执行一句编译一句,而不是一次性全部编译成功,不能提前规划,都是临时调度
容易造成cpu执行调度异常.所以加了一把锁叫GIL
#想要并行的解决办法:
(1)用多进程间接实现线程的并行,并不理想,开辟空间消耗资源
(2)换一个Pypy,Jpython解释器 也不好用,兼容性问题
#程序分为计算密集型和io密集型
对于计算密集型程序会过度依赖cpu,但网页,爬虫,OA办公,这种io密集型的程序里,python多线程绰绰有余
计算密集型,Python比较吃力
1、GIL锁不是python的特点。而是cpython的特点。
2、在cpython解释器中,GIL是一把互斥锁,用来保证进程中同一个时刻只有一个线程在执行。
3、在没有GIL锁的情况下,有可能多线程在执行一个代码的同时,垃圾回收机制对所执行代码的变量直接进行回收,其他的线程再使用该变量时会导致运行错误。
4、总结
对于IO密集型应用,即便有GIL存在,由于IO操作会导致GIL释放,其他线程能够获得执行权限。由于多线程的通讯成本低于多进程,因此偏向使用多线程。
对于计算密集型应用,由于CPU一直处于被占用状态,GIL锁直到规定时间才会释放,然后才会切换状态,导致多线程处于绝对的劣势,此时可以采用多进程+协程。
进程是资源分配的最小单元
线程是cpu执行调度的最小单元
Python先发明的线程,后来添加的进程。所以线程的使用方法与进程一样
#(1) 一个进程里包含了多个线程,线程之间是异步并发
from threading import Thread from multiprocessing import Process import os , time , random def func(i): time.sleep(random.uniform(0.1,0.9)) print("当前进程号:{}".format(os.getpid()) , i) if __name__ == "\_\_main\_\_": #线程里面这句话可以不加 for i in range(10): t = Thread(target=func,args=(i,)) t.start() print(os.getpid())
如下可见,子线程中的进程号与主进程号一样,并且子线程和主进程之间是异步并发的
#(2) 并发的多进程和多线程之间,多线程的速度更快
#多线程速度 def func(i): print( "当前进程号:{} , 参数是{} ".format(os.getpid() , i) ) if __name__ == "\_\_main\_\_": lst = [] startime = time.time() for i in range(10000): t = Thread(target=func,args=(i,)) t.start() lst.append(t) # print(lst) for i in lst: i.join() endtime = time.time() print("运行的时间是{}".format(endtime - startime) ) # 运行的时间是1.8805944919586182 #多进程速度 if __name__ == "\_\_main\_\_": lst = [] startime = time.time() for i in range(10000): p = Process(target=func,args=(i,)) p.start() lst.append(p) # print(lst) for i in lst: i.join() endtime = time.time() print("运行的时间是{}".format(endtime - startime) ) # 运行的时间是101.68004035949707
多进程:1000个进程耗时9.06秒
多线程:多线程之间,数据共享,可以直接操作数据。1000个线程耗时0.087秒,差距巨大,所以对于IO密集型,还是用多线程较快
多进程执行计算密集型,如果各个进程间各计算各的,不用共享数据,由于可以使用多核,比多线程快。
如果是各个进程间数据共享,同步计算最终结果,多进程反而非常慢,远远慢于多线程
#(3) 多线程之间,数据共享
num = 100 lst = [] def func(): global num num -= 1 for i in range(100): t = Thread(target=func) t.start() lst.append(t) for i in lst: i.join() print(num)
多线程之间共享数据,可以直接操作
#用类定义线程,必须手动调用父类__init__方法,必须重载父类run方法,定义自己线程类逻辑
from threading import Thread
import os,time
class MyThread(Thread): def \_\_init\_\_(self,name): # 手动调用父类的构造方法 super().__init__() # 自定义当前类需要传递的参数 self.name = name def run(self): print( "当前进程号{},name={}".format(os.getpid() , self.name) ) if __name__ == "\_\_main\_\_": t = MyThread("我是线程") t.start() print( "当前进程号{}".format(os.getpid()) )
新版:
#自定义线程类
from threading import Thread,current_thread # (1)必须继承父类Thread,来自定义线程类 class MyThread(Thread): def \_\_init\_\_(self,name): # 手动调用父类的构造方法 super().__init__() # 自定义当前类需要传递的参数 self.name = name def run(self): print(f"当前线程的线程号是{current\_thread().ident}") if __name__ == '\_\_main\_\_': for i in range(10): t = MyThread(f"线程{i}") t.start()
# 线程.is\_alive() 检测线程是否仍然存在
# 线程.setName() 设置线程名字
# 线程.getName() 获取线程名字
# 1.currentThread().ident 查看线程id号 新版用current\_thread().ident
# 2.enumerate() 返回目前正在运行的线程列表
# 3.activeCount() 返回目前正在运行的线程数量
getName,setName被弃用了
新版:
def func(): time.sleep(1) if __name__ == "\_\_main\_\_": t = Thread(target=func) t.start() # 检测线程是否仍然存在 print( t.is_alive() ) # 线程.getName() 获取线程名字 print(t.getName()) # 设置线程名字 t.setName("抓API接口") print(t.getName()) from threading import currentThread from threading import enumerate from threading import activeCount def func(): time.sleep(0.1) print("当前子线程号id是{},进程号{}".format( currentThread().ident ,os.getpid()) ) if __name__ == "\_\_main\_\_": t = Thread(target=func) t.start() print("当前主线程号id是{},进程号{}".format( currentThread().ident ,os.getpid()) ) for i in range(5): t = Thread(target=func) t.start() # 返回目前正在运行的线程列表 lst = enumerate() print(lst,len(lst)) # 返回目前正在运行的线程数量 (了解) print(activeCount())
新版:
# ### 线程中的相关属性 import time from threading import Thread,current_thread from threading import enumerate from threading import active_count def func(): time.sleep(1) print(f"当前子线程的线程号{current\_thread().ident}") if __name__ == '\_\_main\_\_': for i in range(5): t = Thread(target=func) t.start() #设置线程名 t.name = f"抓API接口{i}" # 返回目前正在运行的线程列表 lst = enumerate() print(lst,len(lst)) # 返回目前正在运行的线程数量 (了解) print(active_count())
当前运行线程数量,一个主线程,5个子线程
等待所有线程全部执行完毕之后,自己再终止程序,守护所有线程
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注网络安全获取)
零基础入门
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
同时每个成长路线对应的板块都有配套的视频提供:
因篇幅有限,仅展示部分资料
网络安全面试题
绿盟护网行动
还有大家最喜欢的黑客技术
网络安全源码合集+工具包
所有资料共282G,朋友们如果有需要全套《网络安全入门+黑客进阶学习资源包》,可以扫描下方二维码领取(如遇扫码问题,可以在评论区留言领取哦)~
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
blog.csdnimg.cn/img_convert/5072ce807750c7ec721c2501c29cb7d5.png)
所有资料共282G,朋友们如果有需要全套《网络安全入门+黑客进阶学习资源包》,可以扫描下方二维码领取(如遇扫码问题,可以在评论区留言领取哦)~
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-HhhJ1daq-1713019049500)]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。