(并发编程)RLock(与死锁现象),Semaphore,Even事件,线程Queue
一、死锁现象与递归锁
所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
解决方法,递归锁,这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。
一个线程拿到锁,counter加1,该线程内又碰到加锁的情况,则counter继续加1,这期间所有其他线程都只能等待,等待该线程释放所有锁,即counter递减到0为止
from threading import Thread,Lock
import time
mutexA=Lock()
mutexB=Lock()
所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
解决方法,递归锁,这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。
一个线程拿到锁,counter加1,该线程内又碰到加锁的情况,则counter继续加1,这期间所有其他线程都只能等待,等待该线程释放所有锁,即counter递减到0为止
from threading import Thread,Lock
import time
mutexA=Lock()
mutexB=Lock()
class MyThread(Thread):
def run(self):
self.func1()
self.func2()
def func1(self):
mutexA.acquire()
print('\033[41m%s 拿到A锁\033[0m' %self.name)
def run(self):
self.func1()
self.func2()
def func1(self):
mutexA.acquire()
print('\033[41m%s 拿到A锁\033[0m' %self.name)
mutexB.acquire()
print('\033[42m%s 拿到B锁\033[0m' %self.name)
mutexB.release()
print('\033[42m%s 拿到B锁\033[0m' %self.name)
mutexB.release()
mutexA.release()
def func2(self):
mutexB.acquire()
print('\033[43m%s 拿到B锁\033[0m' %self.name)
time.sleep(2)
mutexB.acquire()
print('\033[43m%s 拿到B锁\033[0m' %self.name)
time.sleep(2)
mutexA.acquire()
print('\033[44m%s 拿到A锁\033[0m' %self.name)
mutexA.release()
print('\033[44m%s 拿到A锁\033[0m' %self.name)
mutexA.release()
mutexB.release()
if __name__ == '__main__':
for i in range(10):
t=MyThread()
t.start()
for i in range(10):
t=MyThread()
t.start()
'''
Thread-1 拿到A锁
Thread-1 拿到B锁
Thread-1 拿到B锁
Thread-2 拿到A锁
然后就卡住,死锁了
'''
二、信号量
Semaphore管理一个内置的计数器
# from multiprocessing import Semaphore
Thread-1 拿到A锁
Thread-1 拿到B锁
Thread-1 拿到B锁
Thread-2 拿到A锁
然后就卡住,死锁了
'''
二、信号量
Semaphore管理一个内置的计数器
# from multiprocessing import Semaphore
from threading import Thread,Semaphore,current_thread
import time,random
import time,random
sm=Semaphore(5)
#同时只有5个线程可以获得semaphore,即可以限制最大连接数为5
def go_wc():
sm.acquire()
print('%s 上厕所ing' %current_thread().getName())
time.sleep(random.randint(1,3))
sm.release()
#同时只有5个线程可以获得semaphore,即可以限制最大连接数为5
def go_wc():
sm.acquire()
print('%s 上厕所ing' %current_thread().getName())
time.sleep(random.randint(1,3))
sm.release()
if __name__ == '__main__':
for i in range(23):
t=Thread(target=go_wc)
t.start()
三、线程event(全局变量Falsa or True)
a、案例一: 等待check重置event内的值后,connect从event.wait()后继续运行
from threading import Event,current_thread,Thread
import time
for i in range(23):
t=Thread(target=go_wc)
t.start()
三、线程event(全局变量Falsa or True)
a、案例一: 等待check重置event内的值后,connect从event.wait()后继续运行
from threading import Event,current_thread,Thread
import time
event=Event() #event内部维护着一个全局变量
def check():
print('%s 正在检测服务是否正常....' %current_thread().name)
time.sleep(3)
event.set() #改变event中的全局变量的值
print('%s 正在检测服务是否正常....' %current_thread().name)
time.sleep(3)
event.set() #改变event中的全局变量的值
def connect():
print('%s 等待连接...' %current_thread().name)
event.wait() #等待全局变量的值被重置;如果括号中为1,即只等1秒
print('%s 开始连接...' % current_thread().name)
print('%s 等待连接...' %current_thread().name)
event.wait() #等待全局变量的值被重置;如果括号中为1,即只等1秒
print('%s 开始连接...' % current_thread().name)
if __name__ == '__main__':
t1=Thread(target=connect)
t2=Thread(target=connect)
t3=Thread(target=connect)
c1=Thread(target=check)
t1.start()
t2.start()
t3.start()
c1.start()
t1=Thread(target=connect)
t2=Thread(target=connect)
t3=Thread(target=connect)
c1=Thread(target=check)
t1.start()
t2.start()
t3.start()
c1.start()
b、案例二:三次刷尝试后退出
from threading import Event,current_thread,Thread
import time
from threading import Event,current_thread,Thread
import time
event=Event()
def check():
print('%s 正在检测服务是否正常....' %current_thread().name)
time.sleep(5)
event.set()
print('%s 正在检测服务是否正常....' %current_thread().name)
time.sleep(5)
event.set()
def connect():
count=1
while not event.is_set():#没有被设置为True
if count == 4:
print('尝试的次数过多,请稍后重试')
return
print('%s 尝试第%s次连接...' %(current_thread().name,count))
event.wait(1)
count+=1
print('%s 开始连接...' % current_thread().name)
count=1
while not event.is_set():#没有被设置为True
if count == 4:
print('尝试的次数过多,请稍后重试')
return
print('%s 尝试第%s次连接...' %(current_thread().name,count))
event.wait(1)
count+=1
print('%s 开始连接...' % current_thread().name)
if __name__ == '__main__':
t1=Thread(target=connect)
t2=Thread(target=connect)
t3=Thread(target=connect)
c1=Thread(target=check)
t1.start()
t2.start()
t3.start()
c1.start()
四、线程Queue
import queue
t1=Thread(target=connect)
t2=Thread(target=connect)
t3=Thread(target=connect)
c1=Thread(target=check)
t1.start()
t2.start()
t3.start()
c1.start()
四、线程Queue
import queue
q=queue.Queue(3) #队列:先进先出
q.put(1)
q.put(2)
q.put(3)
# q.put(4) #阻塞
print(q.get())
print(q.get())
print(q.get())
q.put(1)
q.put(2)
q.put(3)
# q.put(4) #阻塞
print(q.get())
print(q.get())
print(q.get())
q=queue.LifoQueue(3) #堆栈:后进先出
q.put('a')
q.put('b')
q.put('c')
print(q.get())
print(q.get())
print(q.get())
q.put('a')
q.put('b')
q.put('c')
print(q.get())
print(q.get())
print(q.get())
q=queue.PriorityQueue(3) #优先级队列:可以以小元组的形式往队列里存值,第一个元素代表优先级,数字越小优先级越高
q.put((10,'user1'))
q.put((-3,'user2'))
q.put((-2,'user3'))
print(q.get())
print(q.get())
print(q.get()) #(10,'user1')
q.put((10,'user1'))
q.put((-3,'user2'))
q.put((-2,'user3'))
print(q.get())
print(q.get())
print(q.get()) #(10,'user1')