進擊のpython
並發編程——信號量,Event,定時器
本節需要了解的就是:
信號量,以及信號量和互斥鎖的區別
了解時間和定時器,以及使用
信號量
信號量也是鎖,本質沒有變!但是他跟互斥鎖同一時間只能有一個任務搶到鎖去執行來說
信號量同一時間可以有很多個任務拿到鎖去執行
如果說互斥鎖是一幫人搶一個廁所,那信號量就是一幫人搶奪多個廁所
def func():
with sm:
print('%s get sm' % threading.current_thread().getName())
time.sleep(3)
if __name__ == '__main__':
sm = Semaphore(5)
for i in range(23):
t = Thread(target=func)
t.start()
上面的代碼可能對with不夠了解,作為上下文管理,也可以用在開關鎖上,就像文件的打開關閉一樣
- Semaphore管理一個內置的計數器,
- 每當調用acquire()時內置計數器+1
- 調用release() 時內置計數器-1
- 計數器不能小於0;當計數器為0時,acquire()將阻塞線程直到其他線程調用release()
Event事件
線程的關鍵特性是每個線程都是獨立運行的,且狀態都是深不可測的
如果需要根據A線程的運行狀態來確定B進程是否運行,那可就太難了
為了解決這個問題,我們就需要Event對象,他可以設置一個標志
等到代碼執行到你想要的狀態的時候,他就把這個狀態設置為真
你就可以接受這個狀態然后執行
他有一些方法:
event.isSet():返回event的狀態值;
event.wait():如果 event.isSet()==False將阻塞線程;
event.set(): 設置event的狀態值為True,所有阻塞池的線程激活進入就緒狀態, 等待操作系統調度;
event.clear():恢復event的狀態值為False
import time
from threading import Thread, Event
def A():
print("我是A線程,我在等待B線程執行結束.. ..")
event.wait()
print("我是A線程,我執行完了!")
def B():
print('我是B線程,我要開始執行了.. .. ')
time.sleep(1)
print('我是B線程,我執行完了!')
event.set()
if __name__ == '__main__':
event = Event()
t1 = Thread(target=A)
t2 = Thread(target=B)
t1.start()
t2.start()
執行結果如下:
我是A線程,我在等待B線程執行結束.. ..
我是B線程,我要開始執行了.. ..
我是B線程,我執行完了!
我是A線程,我執行完了!
可以看到,盡管A先執行的,
但是后面的代碼是在等待着B的執行完畢才執行
所以我們的目的達到了
定時器
程序n秒之后執行
import time
from threading import Thread, Event, Timer
def A():
print("我是A線程,我在等待B線程執行結束.. ..")
event.wait()
print("我是A線程,我執行完了!")
def B():
print('我是B線程,我要開始執行了.. .. ')
time.sleep(1)
print('我是B線程,我執行完了!')
event.set()
def func():
print("都執行完了該我了!", time.time() - start_time)
if __name__ == '__main__':
event = Event()
t = Timer(3, func) # 定時器,3s后執行func
t1 = Thread(target=A)
t2 = Thread(target=B)
start_time = time.time()
t.start() # 發信號
t1.start()
t2.start()
我是A線程,我在等待B線程執行結束.. ..
我是B線程,我要開始執行了.. ..
我是B線程,我執行完了!
我是A線程,我執行完了!
都執行完了該我了! 3.0026462078094482