threading.Semaphore
一個信號量管理一個內部計數器,該計數器因 acquire() 方法的調用而遞減,因 release() 方法的調用而遞增。 計數器的值永遠不會小於零;當 acquire() 方法發現計數器爲零時,將會阻塞,直到其它線程調用 release() 方法。
信號量對象也支持 上下文管理協議 。(可以用with)
class threading.Semaphore(value=1)
該類實現信號量對象。信號量對象管理一個原子性的計數器,代表 release() 方法的調用次數減去 acquire() 的調用次數再加上一個初始值。如果需要, acquire() 方法將會阻塞直到可以返回而不會使得計數器變成負數。在沒有顯式給出 value 的值時,默認爲1。
可選參數 value 賦予內部計數器初始值,默認值爲 1 。如果 value 被賦予小於0的值,將會引發 ValueError 異常。
acquire(blocking=True, timeout=None)
獲取一個信號量。
在不帶參數的情況下調用時:
如果在進入時內部計數器的值大於零,則將其減一併立即返回 True.
如果在進入時內部計數器的值爲零,則將會阻塞直到被對 release() 的調用喚醒。 一旦被喚醒(並且計數器的值大於 0),則將計數器減 1 並返回 True。 每次對 release() 的調用將只喚醒一個線程。 線程被喚醒的次序是不可確定的。
當發起調用時將 blocking 設爲假值,則不進行阻塞。 如果一個無參數調用將要阻塞,則立即返回 False;在其他情況下,執行與無參數調用時一樣的操作,然後返回 True。
當發起調用時如果 timeout 不爲 None,則它將阻塞最多 timeout 秒。 請求在此時段時未能成功完成獲取則將返回 False。 在其他情況下返回 True。
release()
釋放一個信號量,將內部計數器的值增加1。當計數器原先的值爲0且有其它線程正在等待它再次大於0時,喚醒正在等待的線程。
import time
import threading
import random
class DbConnect(threading.Thread):
def __init__(self, l):
threading.Thread.__init__(self)
self.l = l
def run(self):
with self.l:
print(f'{time.strftime("%H:%M:%S")} {self.name} connect to db')
sleep_n = random.randint(1, 5)
print(f'{time.strftime("%H:%M:%S")} {self.name} do something, need {sleep_n} second.')
time.sleep(sleep_n)
print(f'{time.strftime("%H:%M:%S")} {self.name} terminate db')
if __name__ == '__main__':
max_connect_count = 3
semaphore_lock = threading.Semaphore(max_connect_count)
thread_list = list()
thread_list.append(DbConnect(semaphore_lock))
thread_list.append(DbConnect(semaphore_lock))
thread_list.append(DbConnect(semaphore_lock))
thread_list.append(DbConnect(semaphore_lock))
thread_list.append(DbConnect(semaphore_lock))
for cur_thread in thread_list:
cur_thread.start()
for cur_thread in thread_list:
cur_thread.join()
相關鏈接
https://docs.python.org/zh-cn/3/library/threading.html#semaphore-objects