并发:时间段内多个程序轮流执行
并行:同一个时刻不同CPU同时执行
线程:
程序运行中,执行代码的一个分支。每个运行至少都有一个线程.
线程是操作系统调度资源的基础单位
1.创建
import threading
方法:Thread
group: 线程组,目前只能使用None
target: 执行的目标任务名,无需()
args 是一个元祖<位置参数>
kwargs 是一个字典<关键字参数>
name: 线程名,一般不用设置
2.启动线程执行
线程名.start()进行执行
获取当前程序中的线程列表
threading.enumrate()
多线程执行的顺序是无序的
主线程在所有子线程结束后才结束
Daemon线程/守护线程
所有的Daemon线程会随着最后一个 非Demon的退出 而全部退出
setDaemo(True) 将子线程设置为守护线程,跟随主线程一起退出
用于:多线程 + 提前退出 的时候,子线程没有执行完成,程序无法退出
查看线程的标识:print(threading.current_thread())
查看当前程序所有存活的线程列表
如果列表中1个,就是只剩主线程
判断线程是否还存活
线程对象.is_alive()
阻塞等待子线程执行完成
线程对象.join()
创建线程方法:1.使用threading 2.自定义线程,继承threading
方法2过程:
1.继承threading.Thread类及其子类
2.重写其中run方法 子线程会从run开始运行 run中存储的是子线程运行的代码
- 创建子线程 创建子类的对象 对象.start()
4.如果子线程需要更多的参数 重写init方法,并且在其中调用super(父类)
5.strat() != run() strat的作用:创建运行子线程,在子线程中调用run()
主要目的是将线程和线程会执行的代码封装在一个类中
多线程共享全局变量,用global进行注释
线程是程序内部的一条执行线索<线程>
可能造成的问题: 资源竞争/数据竞争
原因:多个线程同时修改一个共享的全局资源,造成数据丢失
解决办法:多线程同步-保持秩序 join和互斥锁
互斥锁:对共享的数据锁定,保证同一时刻只能有一个线程操作
目的:保证多线程共享数据不出现资源竞争和数据错误
格式:
#创建 能保证同一时间点只有一个线程能够占有锁
mutex = threading.Lock()
#申请加锁 如果没锁定可以占有,如果已经被锁定阻塞等待
mutex.acquire() //锁进入locked状态
#解锁 用完一定解锁
mutex.release() //锁进入unlocked状态
好处:确保线程从头到尾执行
坏处:由多线程变化成单线程模式执行,锁用不好容易死锁
死锁
概念:一直等对方释放锁的情景就是死锁
原因:
1.资源的释放方式不对
2.多任务多资源申请,出现互相等待
影响:造成程序无法执行,一直被阻塞
关于线程顺序,正常是主线程和子线程是同步执行,互不相关。
进行输出,查看线程结束的顺序
守护线程设置后,主线程结束,子线程也会结束
设置守护后,看结束效果
通过join可以阻塞等待子线程运行完毕
设置join,看效果
在子线程开启后输出一个话结束主线程,看以上三种方式的结果