1. 程式人生 > >Semaphore 信號量

Semaphore 信號量

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
 7
print(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....[ Thread
-2 ] Run....[ Thread-3 ]
View Code

異常樣例:

 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 times
View Code

Semaphore 信號量