无敌---进程与线程 分手后的思念是犯贱 2022-11-25 00:42 72阅读 0赞 一:进程 1:概念: 进程:操作系统进行资源分配的基本单位。 进程知识点总结: 1:导入进程模块 import multiprocess 2:创建子进程 p1 = multiprocess.Process(target=sing) 3:启动子进程 p1.start() 4:获取进程对象 multiprocessing.current_process() 5:获取进程ID os.getpid() 6:获取父进程ID os.getppid() 7:杀死进程 os.kill(os.getpid(), 9) 8:进程带有参数 元组传参 p1 = multiprocessing.Process(target=sing, args=(6,)) 字典传参 注意:kwargs中键必须和参数名相同 p2 = multiprocessing.Process(target=dance, kwargs={ "num": 4}) 9:设置守护线程 子进程对象名.daemon = True 子进程自杀: 子进程对象名.tarminate() 线程知识点总结: 1:导线程包 import threading 2:创建子线程 t1 = threading.Thread(target=sing) 3:启动子线程 t1.start() 4:获取线程对象 threading.current_thread() 5:线程的传参方式: t1 = threading.Thread(target=sing, args=(3,)) t2 = threading.Thread(target=sing, kwargs={ "num": 3}) 6:创建守护线程: 方案一: t1 = threading.Thread(target=sing,daemon=True) 方案二: t1.setDaemon(True) 方案三: t1.daemon = True 7:设置线程同步 t1.join() 8:锁的使用 创建锁: mutex = threading.Lock() 上锁: mutex.acquire() 解锁: mutex.release() 线程和进程对比: - 关系对比: - 线程依附进程,有进程才有线程 - 一个进程默认有一个线程,也可以有多个线程 - 区别对比: - 全局变量: - 进程不能共享全局变量 - 线程可以共享全局变量,出现资源竞争问题,可以通过互斥锁和线程同步解决。 - 开销上: - 创建进程的开销比创建线程的开销大 - 概念上: - 进程是操作系统资源分配的单位 - 线程是cpu调度的单位 - 关系上: - 线程依附进程存在,不能单独存在 - 稳定性上 - 多进程编程比单进程多线程编程稳定性更好 - 优缺点对比: - 进程:优点(稳定性,可以使用多核)缺点(开销大) - 线程:优点(开销小)缺点(不能使用多核) 2:多进程的使用: 三步走:导入包:import multiprocessing—>创建子进程:multiprocessing.Process(target=sing)—>启动子进程: sing\_process.start() import multiprocessing import time # 跳舞任务 def dance(): for i in range(5): print("跳舞中...") time.sleep(0.2) # 唱歌任务 def sing(): for i in range(5): print("唱歌中...") time.sleep(0.2) if __name__ == '__main__': # 创建跳舞的子进程 # group: 表示进程组,目前只能使用None # target: 表示执行的目标任务名(函数名、方法名) # name: 进程名称, 默认是Process-1, ..... dance_process = multiprocessing.Process(target=dance, name="myprocess1") sing_process = multiprocessing.Process(target=sing) # 启动子进程执行对应的任务 dance_process.start() sing_process.start() 3:获取进程编号和父类进程编号: # 创建一个子进程,在子进程中查看自己的进程编号,和父亲的编号 import multiprocessing import time import os def test(): print("我是子进程:", multiprocessing.current_process()) print("我的进程名是: ", multiprocessing.current_process().name) print("我的当前进程编号是: ", os.getpid()) print("我的父进程的编号是: ", os.getppid()) for i in range(5): print("看我能活几轮...") # 杀死我自己,9是杀死指令 os.kill(os.getpid(), 9) def main(): p1 = multiprocessing.Process(target=test) p1.start() print("我是父进程:", multiprocessing.current_process()) print("我是父进程,我的进程名是: ", multiprocessing.current_process().name) print("我是父进程,我的进程编号是: ", os.getpid()) if __name__ == '__main__': main() 4:进程执行带有参数的任务: import multiprocessing import time def sing(num, name): for i in range(num): print("我叫%s,我要唱我的第%d首歌" % (name, i+1)) time.sleep(1) def dance(num, name): for i in range(num): print("我叫%s,我要跳我的第%d首舞" % (name, i+1)) time.sleep(1) def main(): p1 = multiprocessing.Process(target=sing,args=(3,"小明")) p2 = multiprocessing.Process(target=dance,kwargs={ "num": 5, "name": "小红"}) p1.start() p2.start() if __name__ == '__main__': main() 5:进程之间不共享全局变量: # 思路:建立一个空数组,在两个进程中分别修改,看输出的情况 import multiprocessing import time def test1(): for i in range(5): g_num.append(i) print("我是子进程一,我的g_num: ",g_num) def test2(): print("我是子进程二,我的g_num: ",g_num) g_num = [] def main(): p1 = multiprocessing.Process(target=test1) p2 = multiprocessing.Process(target=test2) p1.start() time.sleep(1) p2.start() print("我是主进程,我的g_num是: ", g_num) if __name__ == '__main__': main() # 运行结果是: # 我是子进程一,我的g_num: [0, 1, 2, 3, 4] # 我是主进程,我的g_num是: [] # 我是子进程二,我的g_num: [] 6:主进程会等待所有的子进程执行结束再结束 # 思路:让子进程花费比自己多的时间 import multiprocessing import time def test(): for i in range(5): print("我是子进程,我正在执行......") time.sleep(0.2) def main(): p = multiprocessing.Process(target=test) p.start() time.sleep(0.5) print("我是主进程,我要结束啦") exit() if __name__ == '__main__': main() # 运行结果: # 我是子进程,我正在执行...... # 我是子进程,我正在执行...... # 我是子进程,我正在执行...... # 我是主进程,我要结束啦 # 我是子进程,我正在执行...... # 我是子进程,我正在执行...... 7:守护主进程以及子进程的销毁: # 思路:设置子进程.daemon=True或者 子进程杀死自己 import multiprocessing import time def test(): for i in range(5): print("我是子进程,我正在执行......") time.sleep(0.2) def main(): p = multiprocessing.Process(target=test) #将子进程设置成守护主线程 # p.daemon=True p.start() time.sleep(0.5) print("我是主进程,我要结束啦") # 在主进程销毁之前杀死子进程 p.terminate() exit() if __name__ == '__main__': main() # # 运行结果: # 我是子进程,我正在执行...... # 我是子进程,我正在执行...... # 我是子进程,我正在执行...... # 我是主进程,我要结束啦 二:线程: 1:定义:线程是CPU调度的基本单位 2:线程的基本使用: import threading import time # 唱歌任务 def sing(): # 扩展: 获取当前线程 # print("sing当前执行的线程为:", threading.current_thread()) for i in range(3): print("正在唱歌...%d" % i) time.sleep(1) # 跳舞任务 def dance(): # 扩展: 获取当前线程 # print("dance当前执行的线程为:", threading.current_thread()) for i in range(3): print("正在跳舞...%d" % i) time.sleep(1) if __name__ == '__main__': # 扩展: 获取当前线程 # print("当前执行的线程为:", threading.current_thread()) # 创建唱歌的线程 # target: 线程执行的函数名 sing_thread = threading.Thread(target=sing) # 创建跳舞的线程 dance_thread = threading.Thread(target=dance) # 开启线程 sing_thread.start() dance_thread.start() 3:线程执行带有参数的任务: # 思路,主线程向子线程中传递一些参数,在子线程中使用这些参数 import threading import time def dance(num,name): for i in range(num): print("我是%s,我在跳第%d个舞,欢迎观赏" % (name, i)) time.sleep(0.2) def sing(num,name): for i in range(num): print("我是%s,我在唱第%d个歌,欢迎倾听" % (name,i)) time.sleep(0.2) def main(): t1 = threading.Thread(target=dance, args=(5,"小红")) # 注意:这里必须键和参数名字相同 t2 = threading.Thread(target=sing,kwargs={ "num": 3,"name":"小绿"}) t1.start() t2.start() if __name__ == '__main__': main() # # 运行结果: # 我是小红,我在跳第0个舞,欢迎观赏 # 我是小绿,我在唱第0个歌,欢迎倾听 # 我是小绿,我在唱第1个歌,欢迎倾听 # 我是小红,我在跳第1个舞,欢迎观赏 # 我是小绿,我在唱第2个歌,欢迎倾听 # 我是小红,我在跳第2个舞,欢迎观赏 # 我是小红,我在跳第3个舞,欢迎观赏 # 我是小红,我在跳第4个舞,欢迎观赏 4:线程之间执行没有顺序 # 思路:创建10个线程,分别打印 import threading import time def test(): # 为什么要休眠一秒?? time.sleep(1) print("我是线程:",threading.current_thread().name) def main(): # 因为循环创建线程,先初始化,再启动,可能的第一个和第二个初始化之间,第一个已经启动完成了。这就导致会顺序创建线程。 # 用睡眠堵塞每个进程,让他们几乎同一时间启动。 for i in range(10): t1 = threading.Thread(target=test) t1.start() if __name__ == '__main__': main() 5:主线程要等待所有子线程结束再结束 # 让子线程花费比主线程更多的时间,使用exit退出主线程 import threading import time def test(): for i in range(5): print("我是子线程.....") time.sleep(1) print("我是子线程,我死啦") def main(): t1 = threading.Thread(target=test) t1.start() time.sleep(1) print("----我是主线程,我马上就死啦") exit() print("----我绝对死透了,你看不到我") if __name__ == '__main__': main() # 运行结果: # 我是子线程..... # ----我是主线程,我马上就死啦 # 我是子线程..... # 我是子线程..... # 我是子线程..... # 我是子线程..... # 我是子线程,我死啦 6:守护主线程的三种方式: import threading import time def test(): print("我是子线程,我要用3s") time.sleep(3) print("主线程没死,我就让你看到") def main(): # 方法一:在创建子线程的参数中加上daemon=True # t1 = threading.Thread(target=test, daemon=True) t1 = threading.Thread(target=test) # 方法二:使用子线程的setDaemo方法 # t1.setDaemon(True) # 方法三:设置子线程的daemon参数=True t1.daemon = True t1.start() time.sleep(1) if __name__ == '__main__': main() 7:线程之间共享全局变量: # 思路:对于一个数据,一个线程向里面写数据,一个线程读数据,看能不能读到另外一个线程写入后的数据 import threading import time def num_add(): for i in range(4): g_num.append(i) print("我是子线程一中的g_num: ",g_num) def num_read(): print("我是子线程二中的g_num: ", g_num) g_num = [] def main(): t1 = threading.Thread(target=num_add) t2 = threading.Thread(target=num_read) t1.start() # 保证子线程一执行完成 time.sleep(1) t2.start() print("我是主线程中的g_num: ", g_num) if __name__ == '__main__': main() # #运行结果 # 我是子线程一中的g_num: [0, 1, 2, 3] # 我是子线程二中的g_num: [0, 1, 2, 3] # 我是主线程中的g_num: [0, 1, 2, 3] 8:线程之间共享全局变量存在的问题: # 思路:如果一个线程给一个全局变量增加100000次,另一个也进行,最后的结果不会是200000,而是在100000到200000之间。 import threading import time def num_add1(): for i in range(1000000): global g_num g_num += 1 print("当子线程一只想结束g_num是:", g_num) def num_add2(): for i in range(1000000): global g_num g_num += 1 print("当子线程二只想结束g_num是:", g_num) g_num = 0 def main(): t1 = threading.Thread(target=num_add1) t2 = threading.Thread(target=num_add2) t1.start() t2.start() if __name__ == '__main__': main() # 运行结果: # 当子线程一只想结束g_num是: 1280374 # 当子线程二只想结束g_num是: 1589925 9:共享变量的解决方案—同步 # 思路:让一个线程执行完,另一个线程再执行 import threading import time def num_add1(): for i in range(1000000): global g_num g_num += 1 print("当子线程一只想结束g_num是:", g_num) def num_add2(): for i in range(1000000): global g_num g_num += 1 print("当子线程二只想结束g_num是:", g_num) g_num = 0 def main(): t1 = threading.Thread(target=num_add1) t2 = threading.Thread(target=num_add2) t1.start() # 让子线程一执行结束再开启子线程二 t1.join() t2.start() if __name__ == '__main__': main() # # 运行结果: # 当子线程一只想结束g_num是: 1000000 # 当子线程二只想结束g_num是: 2000000 10:共享变量的解决方案—互斥锁 # 思路:让可能出现资源竞争的地方所上锁 import threading # 1:创建锁 lock = threading.Lock() def num_add1(): # 2:出现资源竞争的地方所上锁 lock.acquire() for i in range(1000000): global g_num g_num += 1 print("当子线程一只想结束g_num是:", g_num) # 3:执行完释放锁 lock.release() def num_add2(): # 相同地方上锁 lock.acquire() for i in range(1000000): global g_num g_num += 1 print("当子线程二只想结束g_num是:", g_num) # 相同地方解锁 lock.release() g_num = 0 def main(): t1 = threading.Thread(target=num_add1) t2 = threading.Thread(target=num_add2) t1.start() t2.start() if __name__ == '__main__': main() # # 运行结果: # 当子线程一只想结束g_num是: 1000000 # 当子线程二只想结束g_num是: 2000000 # 问题:为啥不在g_num += 1的前后上锁,而是在循环前后上锁,因为频繁开锁和解锁会降低代码执行效率 # 导致程序运行缓慢 11:死锁:一直等待对方释放锁的情景就是死锁 import threading lock = threading.Lock() def get_value(index): lock.acquire() if index >= len(g_num): print("数组下标越界啦") lock.release() return value = g_num[index] print(value) lock.release() g_num = [1,2,3] def main(): for i in range(30): t1 = threading.Thread(target=get_value, args=(i,)) t1.start() if __name__ == "__main__": main()
相关 无敌---进程与线程 一:进程 1:概念: 进程:操作系统进行资源分配的基本单位。 进程知识点总结: 1:导入进程模块 import multiprocess 分手后的思念是犯贱/ 2022年11月25日 00:42/ 0 赞/ 73 阅读
相关 进程与线程 有那么一些零碎的小知识点,偶尔很迷惑,偶尔被忽略,偶然却发现它们很重要,也是各大笔试和面试高频出现考点。这段时间正好在温习这些,就整理在这里,一起学习一起提高!后面还会继续补充 痛定思痛。/ 2022年05月30日 00:19/ 0 赞/ 281 阅读
相关 线程与进程 1.定义 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本 - 日理万妓/ 2022年05月23日 01:56/ 0 赞/ 131 阅读
相关 进程与线程 [进程与线程][Link 1] 推荐一篇讲解的非常透彻且非常形象的文章,阮一峰的一篇博文。 原文链接:[进程与线程的一个简单解释][Link 2] posted @ 秒速五厘米/ 2022年03月22日 11:09/ 0 赞/ 281 阅读
相关 线程与进程 进程 1. 进程是资源分配的最小单位。 2. 开销: 有独立的代码和数据空间,程序切换开销大。 3. 坏境: 能同时运行多个进程(程序)。 4. 内存: 系统在运 骑猪看日落/ 2022年03月17日 10:14/ 0 赞/ 245 阅读
相关 进程与线程 进程,是一个活动的实体,我们平时所说的程序或者可执行文件并不是一个进程,他们都属于被动实体,只有将程序或者可执行文件调入到内存中才能成为一个活动实体,才能称之为进程。 进程是 小鱼儿/ 2022年01月16日 04:27/ 0 赞/ 290 阅读
相关 进程与线程 进程的定义 由于程序在并发执行时,各次执行的结果不同,所以用“程序”这个概念已无法描述程序的并发执行,所以必须引入新的概念 – 进程来描述程序的并发执行。 根据1978 比眉伴天荒/ 2022年01月15日 01:05/ 0 赞/ 302 阅读
相关 进程与线程 进程至少包含三个组成要素:程序快、代码块以及进程控制块; 进程是系统中资源分配和保护的基本单位; 线程作为CPU的调度和分派的基本单位; 每个进程在创建的时候,至少 Dear 丶/ 2022年01月11日 07:49/ 0 赞/ 325 阅读
相关 进程与线程 进程与线程: 基本概念: 进程:进程是正在运行的程序的实例。每个进程都有自己的地址空间,一般情况下,它包括文本区域、数据区域和堆栈。文本区域存储处理器执行的代码;数据区 落日映苍穹つ/ 2021年09月26日 13:08/ 0 赞/ 400 阅读
相关 进程与线程 进程与线程 1 进程 1.1 进程的概念 进程就是正在运行的程序,它代表了程序所占用的内存区域 1.2 进程的特点 独立性 进程是系 忘是亡心i/ 2021年09月07日 06:19/ 0 赞/ 608 阅读
还没有评论,来说两句吧...