python之线程了解部分
一、死锁(了解)
- 死锁产生的4个必要条件:
- 互斥:一个资源同一时刻只允许一个线程进行访问
- 占有未释放:一个线程占有资源,且没有释放资源
- 不可抢占:一个已经占有资源的线程无法抢占到其他线程拥有的资源
- 循环等待:两个或者两个以上的线程,本身拥有资源,不释放资源,并且同时尝试获得其他线程所持有的资源,这种资源的申请关系形成一个闭环的链条
- 死锁的避免:关于死锁的避免,仁者见仁智者见智
- 线程等待时(wait)给予一个默认的等待时间
- 线程之间资源避免相互申请对方的资源,可以通过一些容器来控制并发,比如blockqueue,等等一些线 程安全的容器
- 尽量避免线程在等待的同时申请资源
- 死锁检测,一个线程在等待一段时间后还没有获得资源就放弃申请。对等待时间进行检测
from threading import Thread, Lock
import time
mutexA = Lock()
mutexB = Lock()
class MyThead(Thread):
def run(self):
self.func1()
self.func2()
def func1(self):
mutexA.acquire()
print('%s 抢到A锁' % self.name) # 获取当前线程名
mutexB.acquire()
print('%s 抢到B锁' % self.name)
mutexB.release()
mutexA.release()
def func2(self):
mutexB.acquire()
print('%s 抢到B锁' % self.name)
time.sleep(2)
mutexA.acquire()
print('%s 抢到A锁' % self.name) # 获取当前线程名
mutexA.release()
mutexB.release()
if __name__ == '__main__':
for i in range(10):
t = MyThead()
t.start()
二、递归锁(了解)
- 递归锁的特点
- 可以被连续的acquire和release
- 但是只能被第一个抢到这把锁执行上述操作
- 它的内部有一个计数器
- acquire一次计数加一
- realse一次计数减一
- 只要计数不为0 那么其他人都无法抢到该锁
"""
# 将上述的
mutexA = Lock()
mutexB = Lock()
# 换成
mutexA = mutexB = RLock()
三、信号量(了解)
-
信号量在不同的阶段可能对应不同的技术点
-
在并发编程中信号量指的是锁!!!
"""
如果我们将互斥锁比喻成一个厕所的话
那么信号量就相当于多个厕所
"""
Event事件(了解)
一些进程/线程需要等待另外一些进程/线程运行完毕之后才能运行,类似于发射信号一样
from threading import Thread, Event
import time
event = Event() # 造了个红绿灯
def ligit():
print('红灯亮了')
time.sleep(2)
print('绿地亮了')
# 此时告诉等待绿灯的人可以走了
event.set()
def car(name):
print(F'{name}正在等红灯')
event.wait()
#执行完wait,车才能走
print(F'绿灯了,{name}开车走了')
if __name__ == '__main__':
t = Thread(target=ligit)
t.start()
for i in range(10):
t = Thread(target=car, args=(F'{i+1}车',))
t.start()
四、线程q(了解)
"""
同一个进程下多个线程数据是共享的
为什么先同一个进程下还会去使用队列呢
因为队列是
管道 + 锁
所以用队列还是为了保证数据的安全
"""
import queue
# 我们现在使用的队列都是只能在本地测试使用
# 1 队列q 先进先出
# q = queue.Queue(3)
# q.put(1)
# q.get()
# q.get_nowait()
# q.get(timeout=3)
# q.full()
# q.empty()
# 后进先出q
# q = queue.LifoQueue(3) # last in first out
# q.put(1)
# q.put(2)
# q.put(3)
# print(q.get()) # 3
# 优先级q 你可以给放入队列中的数据设置进出的优先级
q = queue.PriorityQueue(4)
q.put((10, '111'))
q.put((100, '222'))
q.put((0, '333'))
q.put((-5, '444'))
print(q.get()) # (-5, '444')
# put括号内放一个元祖 第一个放数字表示优先级
# 需要注意的是 数字越小优先级越高!!!