线程
线程
目录
一、线程的介绍
1.解释:线程是操作系统能够调度cpu进行运算的最小单位;线程实际上就是拿一堆指令集合去运算
2.特点:线程之间可以进行数据共享
二、python中的线程
1.限制:因为pythonGUI(全局锁)的缘故,每次python解释器只能接收一个线程,使得多线程的并行效果无法完成,也就是即使有多个cpu,在同一时刻,也只有一个cpu处理一个线程
2.适用:I/O密集型任务或函数(交互型)
三、python中创建线程
1.普通创建
1 import threading
2 t1 = threading.Thread(target=func_name, args=(argument1,)) # 创建线程对象
3 t1.start() # 启动线程
2.继承式创建
1 import threading
2
3 class MyThread(threading.Thread):
4 def __init__(self, num):
5 threading.Thread.__init__(self)
6 self.num = num
7
8 def run(self): # 每个线程的运行逻辑
9 pass
10
11 if __name__ == "__main__":
12 t1 = MyThread(1)
13 t1 = MyThread(2)
14
15 t1.start()
16 t2.start()
四、join和Daemon
join() # 线程对象的方法,堵塞住主线程,只有当线程对象完成任务之后,主线程才能向下执行
setDaemon(True) # 线程对象的方法,使得子线程在主线程执行完任务后,自动结束执行。该方法需放在开启线程之前
五、常用方法
Note:
- 同步锁使得多个线程在执行具有同步锁的内容时,相同同步锁中的内容只能被其中一个线程拿到
threading.current_thread() # 显示当前执行的线程
threading.active_count() # 显示当前存在的线程
threading.Lock() # 获得一个同步锁对象,用来防止同时对一个公共数据进行修改
# Lock示例
L = threading.Lock()
L.acquire()
# 需要加锁的内容(需要避免并发的内容)
L.release()
六、线程、进程的理解
线程 # 就像是一个个的会计员
进程 # 就像是一个会计组织
CPU # 就像是一个电脑
函数 # 就像是一份份待统计的数据
pythonGUI # 限制了一个会计组织只能有一个计算器
线程处理任务 # 就像是会计员拿着一些数据,前往电脑中计算;由于一个会计组织中,有多个会计员,所以一个会计员每次处理的数据和占用电脑的时间都是有限制的,每个会计员需要轮流使用电脑。
六、死锁现象
- 形成:获得多把锁对象,在不同的函数中混用锁对象,可能会导致两个线程都在等对方还未释放的锁对象,从而导致两个线程都进入堵塞状态。
- 解决方法:使用递归锁(实际上就是可以被多次调用的一个锁对象)
- 调用方法:threading.Rlock()
七、信号量
- 作用:用来控制每次运行某个任务的线程数量
- 创建
import threading
# 参数为线程数量
semaphore = threading.Semaphore() # or threading.BoundedSemaphore()
# 实例
semaphore.acquire()
# 任务
semaphore.release()
八、条件变量锁
Tips
- 作用:用来进行线程间的通信
- 创建
import threading
# 参数为锁类型,默认为Rlock
lock_con = threading.Condition([lock,Rlock])
# 锁对象的常用方法
acquire()
release()
wait() # 调用后,线程会释放锁并进入等待堵塞
notify() # 调用后,通知等待池激活一个线程
notifyAll() # 调用后,通知等待池激活所有线程
注意:线程被激活后,重新回到加锁那一步
九、同步条件
Tips
- 作用:用来进行线程间的通信,相当于没有锁的Condition
- 创建
event = threading.Event()
# 同步条件对像的常用方法
event.isSet() # 返回event的状态值
event.wait() # 如果event.isSet == False将堵塞线程
event.set() # 设置event的状态值为True,激活阻塞池的所有进程
event.clear() # 设置event的状态值为False
十、队列
Tips
- 作用:可以理解为储存数据的容器,每次只允许一个线程存取数据
- 创建
# 参数为设定容器大小,不填默认无限大
q = queue.Queue() # FIFO先进先出
q = queue.LifoQueue() # LIFO后进先出
q = queue.PriorityQueue() # 优先级输出
# 队列对象常用方法
q.put() # 往队列放数据。可设置,block为False,使得队列满时报错;True时是堵塞状态,其他数据不能进入。timeout可定一个超时时间
q.get() # 往队列取数据
q.size() # 放回队列大小
q.full() # 判断队列是否满
q.empty # 判断队列是否空