线程中的信号量和事件

# 线程中的信号量
    # 和进程中的信号量概念一样,创建好信号量的深度后,同一时间只有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()

猜你喜欢

转载自www.cnblogs.com/whylinux/p/9858941.html