Semaphore 信號量
阿新 • • 發佈:2018-01-14
tar pri 輸出結果 [] connect eas 釋放 方法 超時時間
Semaphore線程同步機制,當調用acquire()時,內部計數器數值增加;調用release()時,內部計數器遞減;計數器值不能小於0,如果等於0,acquire()方法被阻塞,需要等待其他線程調用release()方法。
BoundedSemaphore(value=1),對信號量的計數器設置界限,默認值為1,計數器的值不能大於設定的值,否則拋出ValueError;如果信號量釋放過多,則表示程序有Bug。
信號量通常用來保護容量有限的資源,例如鏈接數據庫服務器,官方示例偽代碼:
maxconnections = 5 # ... pool_sema = BoundedSemaphore(value=maxconnections) with pool_sema: conn= connectdb() try: # ... use connection ... finally: conn.close()
正常樣例:
1 from threading import Thread, BoundedSemaphore, currentThread 2 import time 3 4 sema = BoundedSemaphore(value=2) # 信號量界限為2 5 def run(): 6 sema.acquire() # 每次執行,線程都會調用acquire、release 7print(‘Run....[ %s ]‘ % currentThread().getName()) 8 time.sleep(1) 9 sema.release() 10 11 threads = [] 12 for i in range(3): 13 t = Thread(target=run) 14 t.start() 15 threads.append(t) 16 17 for item in threads: 18 item.join()
正常輸出:
Run....[ Thread-1 ] Run....[ ThreadView Code-2 ] Run....[ Thread-3 ]
異常樣例:
1 from threading import Thread, BoundedSemaphore, currentThread 2 import time 3 4 sema = BoundedSemaphore(value=2) 5 def run(): 6 """ 7 第三個線程會報錯,這裏超時時間為0.5s,因為前兩個線程需要在1s之後才可以調用release()方法, 8 所以在等待其他線程調用release()方法時超時,導致第三個線程調用acquire()方法失敗, 9 信號量內部計數器沒有減少,但是之後又去調用release()方法,計數器數值超出設定界限,所以拋出ValueError 10 """ 11 sema.acquire(timeout=0.5) 12 print(‘Run....[ %s ]‘ % currentThread().getName()) 13 time.sleep(1) 14 try: 15 sema.release() 16 except ValueError as e: 17 print(‘Error:‘, e) 18 19 threads = [] 20 for i in range(3): 21 t = Thread(target=run) 22 t.start() 23 threads.append(t) 24 25 for item in threads: 26 item.join()
異常輸出結果:
Run....[ Thread-1 ] Run....[ Thread-2 ] Run....[ Thread-3 ] Error: Semaphore released too many timesView Code
Semaphore 信號量