1.什么是线程?
计算机中程序运行得实际执行者就是线程,线程又称为轻量级进程每个进程至少会有一个线程,至少有一个主线程,线程的创建由threading模块来执行。
2.多线程开发
线程属性·:
Event 事件类,用于线程同步
Condition 条件类,用于线程同步
Lock/RLock 锁类,用于线程同步
Timer 延时线程,用于在一定事件后执行一个函数
Semaphore/BoundedSemaphore 信号量类,用于线程同步
Barrir 线程同步类型
active_count()/activeCount() 获取当前 alive 状态的所有线程数量
current_thread()/currentThread() 获取当期正在执行的线程对象
get_ident() 获取运行中程序当前线程的唯一编号
enumerate() 获取所有 alive 状态线程列表
local 线程局部数据类
stack_size([size]) 获取线程占用内存栈的大小
main_thread() 获取主线程
3.函数式开发实现
通过threading 模块的Thread函数,可以实现多线程程序的运行
火车票售票案例:
两种模式:1.单线程实现模式:相当于只有一个窗口售票
Threading.Thread(target=()):
2.多线程售票:相当于多个窗口同时售票
if name == "main":
定义多个线程(窗口)
t1 = threading.Thread(name="窗口 1", target=sale_ticket)
t2 = threading.Thread(name="窗口 2", target=sale_ticket)
t3 = threading.Thread(name="窗口 3", target=sale_ticket)
t4= threading.Thread(name="窗口 2", target=sale_ticket)
t5 = threading.Thread(name="窗口 3", target=sale_ticket)
启动五个窗口
t1.start()
t2.start()
t3.start()
T4.start()
T5.start()
3.1线程状态-join
Join:线程的join状态是独占模式,当前线程独占cpu单元,必须等待当前线程执行
完成或者超时以后,才能运行其他线程
火车票售票:独占执行
五个线程同时执行,第一个线程以独占模式执行
那麽其他线程要等到该线程执行完成才能执行
T1.join()
t2.start()
t3.start()
T4.start()
T5.start()
3.2线程管理-锁(Lock\RLock)
多线程程序在运行时,多个线程访问同一部分数据时,很容易造成数据冲突的情况,很容易出现执行结果不符合期望的情况,这就需要锁来解决这个情况
有两种锁:同步锁/互斥锁:Lock;可重用锁:Rlock
创建锁 lock = threading.Lock()
定义锁:lock.acquire()
开锁:lock.release()
3.3死锁-线程管理(Dead Lock)
线程锁固然功能强大,可以管理多个线程之间的共享数据问题
但是同时它的强大也带来了比较纠结的问题,需要开发人员对于锁定的数据有一个良好的认
知,否则特别容易造成死锁的现象,
由于计算机运算速度较快,所以有两种方案可以将问题放大
⚫ 给执行函数添加休眠时间
⚫ 添加线程数量
死锁并不是每次都会出现的,而是程序在执行过程中,根据系统 CPU 时间片的切换机制恰好遇到了重复上锁的情况,就会死锁
实际项目开发过程中,一定要注意死锁情况的影响! ! ! !
这样的情况可以通过可重用锁 RLock 进行锁定处理!
PYTHON 中的互斥锁,只有两种状态,locked 和 unlocked,如果一旦重复上锁就会死锁
但是可重用锁 RLock,在锁定的基础上提供了一个计数器 counter,可以计算上锁的次数然
后通过 release()解锁时就会重新运算计数器,等待计数器清零时所有锁全都释放了!
3.4油条的故事-event实现
两个线程的通信:事件对象:threading.Event
set()添加标记
wait()线程等待-如果当前事件对象被标记~继续运行
clear()清除标记
3.5线程管理-条件(condition)
线程条件 Condition 对象,也是多线程并发模式下一种线程之间通信的友好支持
在某些情况下,我们需要多个线程在运行过程中根据实际操作情况,不同功能的线程在满足
对应的条件时等待、启动两种状态之间进行切换
Condition 对象的属性和方法
名称 描述
acquire() 锁定
release() 解锁
wait() 释放锁,同时阻塞当前线程,等待被唤醒
wait_for() 释放锁,同时阻塞当前线程,等待被唤醒
notify() 唤醒
notify_all() 唤醒所有等待该 condition 条件的线程
线程实现——condition实现
需求:生产者消费者问题,描述的是多个线程之间的通信处理方式和手段。
多个生产者线程生产食品放到指定的食品容器中,并唤醒所有的消费者线程开始就餐
如果食品容器容量饱和,则所有生产者线程等待
3.6线程管理——队列(Queue)
多线程并发编程的重点:是线程之间共享数据的访问问题和线程之间的通信问题
为了解决问题,PYTHON 提供了一个数据类型【队列】可以用于在多线程
并发模式下,安全的访问数据而不会造成数据共享冲突
python 中的 queue 模块提供的队列类型 Queue 的操作模式如下
名称 描述
put([timeout=None]) 向队列中添加数据,队列如果满了,一直阻塞直到超时或者队
列中有数据被删除之后添加成功
get([timeout=None]) 从队列中获取数据,如果队列为空,一直阻塞直到超时或者队
列中添加数据之后获取成功
3.7面向对象开发实现
pytjon人性化的提供了更多强大的多线程开发编程
面向对象的操作模式,让多线程并发更加优秀、
3.8基本语法
面向对象的多线程,主要是让自定义类型派生自 threading.Thread 类
重写 Thread 类型的 run()方法,然后创建自定义线程类的对象之后,调用 start()方法启动