並發編程---死鎖||遞歸鎖---信號量---Event事件---定時器
阿新 • • 發佈:2018-04-23
遞歸 spa sleep 事件 lang tin lap 計數器 name
死鎖
互斥鎖:Lock(),互斥鎖只能acquire一次
遞歸鎖: RLock(),可以連續acquire多次,每acquire一次計數器+1,只有計數為0時,才能被搶到acquire
# 死鎖 from threading import Thread,Lock import time mutexA = Lock() mutexB = Lock() class MyThread(Thread): def run(self): self.f1() self.f2() def f1(self): mutexA.acquire()死鎖print(‘%s 拿到了A鎖‘ %self.name) mutexB.acquire() print(‘%s 拿到了B鎖‘ % self.name) mutexB.release() mutexA.release() def f2(self): mutexB.acquire() print(‘%s 拿到了B鎖‘ % self.name) time.sleep(0.1) mutexA.acquire() print(‘%s 拿到了A鎖‘ % self.name) mutexB.release() mutexA.release()if __name__ == ‘__main__‘: for i in range(10): t=MyThread() t.start() ‘‘‘ 打印結果: Thread-1 拿到了A鎖 Thread-1 拿到了B鎖 Thread-1 拿到了B鎖 Thread-2 拿到了A鎖 ‘‘‘
#互斥鎖只能acquire一次 from threading import Thread,Lock mutexA = Lock() mutexA.acquire() mutexA.release() #遞歸鎖:可以連續acquire多次,每acquier一次計數器就+1,只有計數為0時,才能被其他線程強到遞歸鎖from threading import Thread,RLock import time mutexB = mutexA = RLock() class MyThread(Thread): def run(self): self.f1() self.f2() def f1(self): mutexA.acquire() print(‘%s 拿到了A鎖‘ %self.name) mutexB.acquire() print(‘%s 拿到了B鎖‘ % self.name) mutexB.release() mutexA.release() def f2(self): mutexB.acquire() print(‘%s 拿到了B鎖‘ % self.name) time.sleep(2) mutexA.acquire() print(‘%s 拿到了A鎖‘ % self.name) mutexB.release() mutexA.release() if __name__ == ‘__main__‘: for i in range(10): t=MyThread() t.start() ‘‘‘ 打印結果: Thread-1 拿到了A鎖 Thread-1 拿到了B鎖 Thread-1 拿到了B鎖 Thread-1 拿到了A鎖 Thread-2 拿到了A鎖 Thread-2 拿到了B鎖 Thread-2 拿到了B鎖 Thread-2 拿到了A鎖 Thread-4 拿到了A鎖 Thread-4 拿到了B鎖 Thread-4 拿到了B鎖 Thread-4 拿到了A鎖 Thread-6 拿到了A鎖 Thread-6 拿到了B鎖 Thread-6 拿到了B鎖 Thread-6 拿到了A鎖 Thread-8 拿到了A鎖 Thread-8 拿到了B鎖 Thread-8 拿到了B鎖 Thread-8 拿到了A鎖 Thread-10 拿到了A鎖 Thread-10 拿到了B鎖 Thread-10 拿到了B鎖 Thread-10 拿到了A鎖 Thread-5 拿到了A鎖 Thread-5 拿到了B鎖 Thread-5 拿到了B鎖 Thread-5 拿到了A鎖 Thread-9 拿到了A鎖 Thread-9 拿到了B鎖 Thread-9 拿到了B鎖 Thread-9 拿到了A鎖 Thread-7 拿到了A鎖 Thread-7 拿到了B鎖 Thread-7 拿到了B鎖 Thread-7 拿到了A鎖 Thread-3 拿到了A鎖 Thread-3 拿到了B鎖 Thread-3 拿到了B鎖 Thread-3 拿到了A鎖 ‘‘‘
信號量
信號量也是一把鎖,可以指定信號量為5,對比互斥鎖同一時間只能有一個任務搶到鎖去執行
信號量同一時間可以有5個任務拿到鎖去執行
信號量:同一時間有多個線程在進行
from threading import Thread,Semaphore,currentThread import time,random sm=Semaphore(3) #廁所的坑 def task(): # sm.acquire() # print(‘%s in‘ %currentThread.getName()) # sm.release() with sm: print(‘%s in‘ %currentThread().getName()) time.sleep(random.randint(2,3)) if __name__ == ‘__main__‘: for i in range(10): t=Thread(target=task) t.start() ‘‘‘ 打印結果: Thread-1 in Thread-2 in Thread-3 in Thread-4 in Thread-5 in Thread-6 in Thread-7 in Thread-9 in Thread-8 in Thread-10 in ‘‘‘信號量
Event事件
event.isSet(): 返回event的狀態值
event.wait():如果 event.isSet()==False將阻塞線程
event.set(): 設置event的狀態值為True,所有阻塞池的線程激活進入就緒狀態,等待操作系統調度
event.clear(): 恢復event的狀態值為False
from threading import Thread,Event import time event = Event() # event.wait() 在原地等,指導執行到event.set() # event.set() 等待結束 def student(name): print(‘學生%s 正在聽課‘ %name) event.wait(2) print(‘學生%s 課間活動‘ %name) def teacher(name): print(‘老師%s 正在授課‘ %name) time.sleep(5) event.set() if __name__ == ‘__main__‘: stu1 = Thread(target=student,args=(‘alex‘,)) stu2 = Thread(target=student,args=(‘yang‘,)) stu3 = Thread(target=student,args=(‘hang‘,)) tea1 = Thread(target=teacher,args=(‘ding‘,)) stu1.start() stu2.start() stu3.start() tea1.start() ‘‘‘ 打印結果: 學生alex 正在聽課 學生yang 正在聽課 學生hang 正在聽課 老師ding 正在授課 學生hang 課間活動 學生yang 課間活動 學生alex 課間活動 ‘‘‘ #設置連接的超時時間 from threading import Thread,Event,currentThread import time event = Event() def conn(): n=0 while not event.is_set(): if n == 3: print(‘%s try too many‘ %currentThread().getName()) return print(‘%s try %s‘ %(currentThread().getName(),n)) event.wait(0.5) n+=1 print(‘%s is connecting‘ %currentThread().getName()) def check(): print(‘%s is checking‘ %currentThread().getName()) time.sleep(5) event.set() if __name__ == ‘__main__‘: for i in range(3): t=Thread(target=conn) t.start() t=Thread(target=check) t.start() ‘‘‘ 打印結果: Thread-1 try 0 Thread-2 try 0 Thread-3 try 0 Thread-4 is checking Thread-1 try 1 Thread-3 try 1 Thread-2 try 1 Thread-1 try 2 Thread-3 try 2 Thread-2 try 2 Thread-1 try too many Thread-3 try too many Thread-2 try too many ‘‘‘Event
定時器
定時器:隔一段時間,執行一個任務,每啟動一個定時器,就等於啟動一個線程
t=Timer(5,task,args=(‘egon‘,))
t.start()
t.cancel()
# from threading import Timer # # def task(name): # print(‘hello %s‘ %name) # # t=Timer(5,task,args=(‘egon‘,)) # t.start() #驗證碼 from threading import Timer import random class Code: def __init__(self): self.make_cache() def make_cache(self,interval=60): self.cache = self.make_code() print(self.cache) self.t = Timer(interval,self.make_cache) self.t.start() def make_code(self,n=4): res=‘‘ for i in range(n): s1 = str(random.randint(0,9)) s2 = chr(random.randint(65,90)) res+=random.choice([s1,s2]) return res def check(self): while True: code = input(‘輸入你的驗證碼>>: ‘).strip() if code.upper() == self.cache: print(‘驗證碼輸入正確‘) self.t.cancel() break obj=Code() obj.check() ‘‘‘ 打印結果: X095 輸入你的驗證碼>>: X095 驗證碼輸入正確 ‘‘‘定時器
並發編程---死鎖||遞歸鎖---信號量---Event事件---定時器