線程中的信號量和事件


# 線程中的信號量
    # 和進程中的信號量概念一樣,創建好信號量的深度后,同一時間只有n個線程可以訪問被信號量保護的代碼



# 同一時間只有4個線程可以訪問被信號量保護的代碼
# import time
# from threading import Semaphore, Thread
#
# def func(sem, a, b):
#     sem.acquire()
#     time.sleep(1)
#     print(a + b)
#     sem.release()
#
# if __name__ == '__main__':
#
#     sem = Semaphore(4)  # 創建信號量,4個深度
#     for i in range(10):
#         t = Thread(target=func, args=(sem, i, i + 5))
#         t.start()



# 線程中的事件
    # 和進程中的事件概念一樣
    # 事件的狀態
        # False狀態
            # wait()阻塞
        # True狀態
            # wait()非阻塞
    # 改變事件的狀態
        # clear()設置事件狀態為Flase,即使wait()阻塞
        # set()設置事件狀態為True,即使wait()非阻塞

# 線程中的事件例子
    # 模擬
        # 連接數據庫
        # 檢測數據庫的可連接情況
        # 起兩個線程
            # 第一個線程:連接數據庫
                # 第一個線程會阻塞等待這個事件,等待一個信號,這個信號來告訴自己和數據庫之間的網絡是通的
            # 第二個線程:檢測與數據庫之間的網絡是否是通的
                # 模擬延時一會后,將事件的狀態設置為True,使這個事件變為非阻塞,此時第一個線程就會檢測到該事件為非阻塞,則會知道與數據庫之間的網絡是通的

import time
import random
from threading import Event, Thread

def connect_db(e):
    '''
    模擬檢測數據庫可以連接后,則連接數據庫
    :param e:
    :return:
    '''
    count = 3
    while count > 0:
        #e.wait()    # 如果事件e為False,則會阻塞在這里
        e.wait(1)    # wait可以帶參數,表示如果事件是阻塞的話,這里最長會阻塞1S中
        if e.is_set() == True:  # 檢測下事件是否為非阻塞,因為到這里可能是wait阻塞超時導致(這種事件狀態還是為False阻塞),也可能確實是檢測網絡的線程發的解除阻塞信號
            print('連接數據庫')
            break
        else:
            print('連接數據庫超時')
            count -= 1
    else:
        print('連接數據庫到了上限次還沒有連接數據庫成功')
        raise TimeoutError  # 主動拋出一個超時異常

def check_web(e):
    '''
    檢測數據庫可連接情況,模擬延時一會后,將事件設置為True,變為非阻塞,表示網絡是通的
    :param e: 事件
    :return:
    '''
    time.sleep(random.randint(0, 5))
    e.set()

if __name__ == '__main__':
    e = Event() # 事件創建好后,默認是False阻塞的
    t = Thread(target=connect_db, args=(e, ))
    t2 = Thread(target=check_web, args=(e, ))
    t.start()
    t2.start()

    t.join()
    t2.join()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM