线程和进程
"""
线程介绍:概述:进程是CPU分配资源的基本单位, 线程是CPU调度资源的基本单位.线程是依附于进程的, 即: 1个进程至少会有1个线程.多线程也是实现多任务的一种方式.大白话:进程 -> 车, 线程 -> 车道, 即: 线程是进程的执行路径, 单元.线程的实现步骤:1. 导包.2. 创建线程对象, 关联目标函数.3. 启动线程.案例:1. 线程入门.2. 带参数的线程.3. 测试线程之间数据是共享的.4. 线程共享数据可能出现安全问题(非法值) -> 互斥锁解决.5. 线程和进程的区别.结论(记忆):1. 进程是CPU分配资源的基本单位, 线程是CPU调度资源的基本单位.2. 多进程, 多线程执行具有随机性, 原因是因为: CPU在做着高效的切换.3. 操作系统分配资源的时候(即: 资源调度策略), 一般有两种调度方式:均分时间片: 每个任务获得到CPU的时间都是几乎一致的, 可能无法高效利用CPU等资源.抢占式调度: 谁抢到, 谁执行. Python, Java均是如此.4. 进程 和 线程的区别是:关系对比:线程依赖进程, 且1个进程至少有1个线程.区别对比:1. 进程之间数据是相互隔离的, 线程之间数据是相互共享的.2. 进程是CPU分配资源的基本单位, 线程是CPU调度资源的最小单位.3. 进程的资源开销比线程的资源开销要大, 但是会更稳定.4. 线程不能独立执行, 必须依附于进程才可以.优缺点对比:进程: 可以使用多核, 资源开销相对较大.线程: 不能使用多核, 资源开销相对较小.
"""
线程和进程多任务概述让多个任务同时执行 或者 交替执行目的充分利用CPU资源提高程序的执行效率表现形式并行指的是多个任务同时执行前提是需要多核CPU并发针对于单核CPU来讲同时又多个任务请求执行 但是同一个瞬间CPU只能执行1个任务 于是就安排他们交替执行因为时间间隔非常短 我们看起来好像是同时执行的 其实不是具体实现多进程多线程多进程概述一个可执行文件就是一个进程 例如: XXX.exe操作步骤1.导包import multiprocessing2.创建进程对象p1 = multiprocessing.Process(target=函数名, args=(传参), name='进程名')3.启动进程p1.start()关于创建进程对象时的几个参数target关联函数名name进程名字 默认Process_n n是从1开始的args以元组的形式传参 要求个数 顺序 与函数保持一致kwargs以字典形式传参 要求 个数 键名要和函数的形参名保持一致 对顺序无要求如何获取进程ID好处为了方便我们管理进程 知道进程之间的关系获取当前进程IDos.getpid()multiprocessing.current_process().pid获取当前进程的父级IDos.getppid()进程的特点进程之间数据是相互的 隔离的默认情况下 主进程会等待子进程执行结束再结束如何实现主进程结束 子进程同步结束方式一设置子进程为 守护进程 特点: 当非守护进程执行结束 它的所有守护进程也会强制结束进程名.daemon = True方式二 手动终止子进程 不推荐 会导致 子进程变成僵尸进程 (main进程即使结束了) 不会立即释放子进程的进程资源进程名.terminate()多线程概述进程的执行路径 执行单元一个进程的内部至少有一个线程 (主线程)操作步骤1.导包import threading2.创建线程对象线程名=threading.Thread(target= 函数名)3.启动线程线程名.start()关于创建线程对象的几个参数target关联目标函数name线程名args传参 元祖形式 数量和顺序要保持一致kwargs传参 字典形式 键名要和函数参数名一致 顺序无要求如何获取线程idthreading.current_thread().identthreading.get_ident()函数内 self.thread_id线程的特点线程之间数据是互相共享的为了解决安全问题 有互斥锁 使用时注意用同一把锁 且注意不能形成死锁使用方法1.导包 import threading2.创建锁 my_lock = threading.Lock()3,使用锁 my_lock.acquire()4.释放锁 my_lock.release()线程和进程的区别关系线程依赖进程 且一个进程至少有一个线程区别1.进程之间数据是相互隔离的 线程之间数据是共享的2.进程是CPU分配资源的最小单位 线程是CPU调度资源的最小单位3.进程的资源开销比线程的发 但是更稳定4.线程不能独立执行 必须依附进程优缺点对比进程: 可以使用多核 资源开销相对较大线程 不能使用多核 资源开销相对较小
简答题
请说出至少4点进程与线程之间的区别?
"""
进程与线程的区别:1.线程不能独立执行 要依附于进程2,进程的开销相对较大 但更稳定3.进程是CPU分配资源的最小单位 线程是CPU调度资源的最小单位4.进程可以多核 但线程不能5.进程之间数据是隔离的 线程之间数据是共享的
"""
若要完成多任务编程,可以采用哪些措施?操作流程基本是怎样的?请简要描述一下。
"""
使用多进程进行编程
1.导入multiprocessing包
2.编写具体函数
3.为每个函数创建进程对象
4.开启各个进程
"""
实操题
(1)请使用多任务形式完成:一边编程、一边听音乐、一边跟同事聊天。要求如下:
# a.使用多进程完成;"""
import multiprocessing, timedef coding():for i in range(1, 11):time.sleep(0.1)print(f'正在编写第{i}行代码.')def music():for i in range(1, 11):time.sleep(0.1)print(f'正在闯第 {i} 关...')def chat():for i in range(1, 11):time.sleep(0.1)print(f'正在和 {i} 个人一起聊天......')if __name__ == '__main__':p1 = multiprocessing.Process(target=coding)p2 = multiprocessing.Process(target=music)p3 = multiprocessing.Process(target=chat)p1.start()p2.start()p3.start()
"""# b.使用多线程完成;
import threading, timedef coding():for i in range(1, 11):time.sleep(0.1)print(f'正在编写第{i}行代码.')def music():for i in range(1, 11):time.sleep(0.1)print(f'正在闯第 {i} 关...')def chat():for i in range(1, 11):time.sleep(0.1)print(f'正在和 {i} 个人一起聊天......')if __name__ == '__main__':p1 = threading.Thread(target=coding)p2 = threading.Thread(target=music)p3 = threading.Thread(target=chat)p1.start()p2.start()p3.start()
# c.分别观察与对比多进程、多线程的执行效果。
# 线程的执行效率高 CPU的利用率高 会有抢任务的感受 偶尔还没跑完一个函数 就被其他函数抢走资源执行了
(2)编写一个线程死锁的案例,并描述一下原因
# a.提交代码和运行效果;
"""import threading, timecount = 0
my_lock = threading.Lock()
my_lock2 = threading.Lock()def method1():my_lock.acquire()for i in range(1000):global countcount += 1my_lock2.acquire()print(f'method1函数的count: {count}')my_lock.release()def method2():my_lock2.acquire()for i in range(1000):global countcount += 1print(f'method2的count: {count}')my_lock2.release()if __name__ == '__main__':t1 = threading.Thread(target=method1)t2 = threading.Thread(target=method2)t1.start()t2.start()
"""
# b.描述原因;# 函数method1和method2同时执行 method2函数中 需要获取my_lock2锁 他需要等待method1释放锁 但是method1没有晒放 所以会一直等待
“”“”
案例:
演示线程环境, 操作共享变量, 引发安全问题.
需求:
定义两个函数, 实现循环100W次, 每循环一次给全局变量加1, 创建两个子线程, 关联两个函数, 查看结果.
发现问题, 程序值出现了非法值的情况:
问题描述: 多线程并发, 操作共享变量, 引发安全问题, 即: 非法值问题.
产生原因:
正常情况:
1. 当 g_num的值为1的时候, 此时 t1线程抢走资源, 执行了一次累加, 然后 g_num = 0 -> g_num = 1
2. 然后 t2线程抢走资源, 执行一次累加, 然后: g_num = 1 -> g_num = 2
3. 这个是正常情况, 累加2次, g_num的值 增量了 2.
非法情况:
1. 当 g_num的值为 1 的时候, 此时t1先抢到资源, 然后读取 g_num的值 为 1
2. 当t1线程还没有来得及对 g_num变量值做 + 1操作时, 被 t2线程抢走了资源, 此时 t2线程读到的 g_num的值依旧1
3. 此时就会出现安全问题, 即: 累加了 2 次, 但是 g_num的值只增加了 1.
t1线程: g_num = 0 -> g_num = 1
t2线程: g_num = 0 -> g_num = 1
解决方案:
采用 加锁的 思想解决.
线程同步介绍:
概述:
多线程并发, 操作同一数据, 有可能引发安全问题, 就需要用到 线程同步(加锁)解决.
步骤:
1. 创建锁.
2. 在合适的地方加锁.
3. 在合适的时机释放锁.
细节:
1. 必须使用同1把锁, 否则可能出现锁不住的情况.
2. 必须在合适的时机释放锁, 否则可能出现 “死锁"的情况.
“””
# 导包
import threading# 1. 定义全局变量
g_num = 0 # global number: 全局变量.'# 创建锁(在Python中, 称之为: 互斥锁).
my_lock = threading.Lock()
# my_lock2 = threading.Lock()# 2. 定义函数, 对 全局变量, 累加 100W次.
def method1():# 加锁.my_lock.acquire()for i in range(1000000):# 声明是全局变量.global g_num# 变量值累加1g_num += 1print(f'method1函数, g_num: {g_num}')# 释放锁.my_lock.release()# 3. 定义函数, 对 全局变量, 累加 100W次.
def method2():# 加锁.my_lock.acquire()# my_lock2.acquire()for i in range(1000000):# 声明是全局变量.global g_num# 变量值累加1g_num += 1print(f'method2函数, g_num: {g_num}')# 释放锁.my_lock.release()# my_lock2.release()# 4. 在main函数中测试.
if __name__ == '__main__':# 4.1 创建子线程, 关联函数.t1 = threading.Thread(target=method1)t2 = threading.Thread(target=method2)# 4.2 开启线程.t1.start()t2.start()
坚持分享 共同进步 如有错误 欢迎指出