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