信号量也是一把锁,可以指定信号量为5,对比互斥锁同一时间只能有一个任务抢到锁去执行,信号量同一时间可以有5个任务拿到锁去执行,如果说互斥锁是合租房屋的人去抢一个厕所,那么信号量就相当于一群路人争抢公共厕所,公共厕所有多个坑位,这意味着同一时间可以有多个人上公共厕所,但公共厕所容纳的人数是一定的,这便是信号量的大小
Copy from threading import Thread, Semaphore
import threading
import time
def func():
sm.acquire()
print('%s gets sm' % threading.current_thread().getName())
time.sleep(3)
sm.release()
if __name__ == '__main__':
sm = Semaphore(5)
for i in range(23):
t = Thread(target=func)
t.start()
Copy - Semaphore管理一个内置的计数器,如value=5
- 每当调用acquire()时内置计数器-1,调用release() 时内置计数器+1
- 计数器不能小于0,当计数器为0时,acquire()将阻塞线程直到其他线程调用release()
Copy from threading import Event
event.is_set():返回event的状态值;
event.wait():如果 event.is_set()==False将阻塞线程
event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度
event.clear():恢复event的状态值为False
例如,有多个工作线程尝试链接MySQL,我们想要在链接前确保MySQL服务正常才让那些工作线程去连接MySQL服务器,如果连接不成功,都会去尝试重新连接。那么我们就可以采用threading.Event机制来协调各个工作线程的连接操作
Copy import random
import threading
import time
from threading import Thread, Event
def conn_mysql():
count = 1
while not event.is_set():
if count > 10:
return TimeoutError('超时连接')
print('<%s>第%s次尝试连接' % (threading.current_thread().getName(), count))
event.wait(0.5)
count += 1
print('<%s>连接成功' % threading.current_thread().getName())
def check_mysql():
print('[%s]正在检查mysql' % threading.current_thread().getName())
time.sleep(random.randint(2, 4))
event.set()
if __name__ == '__main__':
event = Event()
event = Event()
conn1 = Thread(target=conn_mysql)
conn2 = Thread(target=conn_mysql)
check = Thread(target=check_mysql)
conn1.start()
conn2.start()
check.start()
Copy from threading import Timer
def hello():
print('Hello World')
if __name__ == '__main__':
t = Timer(3, hello)
t.start()