信号量Semaphore
# !/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2022/1/18 9:33
# @Author : 波澜不惊
# @File : 信号量Semaphore.py
# 信号量也是一把锁,用来控制线程并发数
# 信号量通过一个内置的计数器,当加锁时,该数-1,释放时该数+1
# 计数器不能小于0,当计数器为0时,加锁操作会让线程进入阻塞状态,
# 直到其他线程释放锁之后计数器有空位子
# BoundedSemaphore与Semaphore的唯一区别在于前者将调用release()时检查计数器的值是否超过了初始值
# 如果超过了将抛出一个异常
import threading
import time
from sys import stdout
class myThread(threading.Thread):
def run(self):
if semaphore.acquire():
stdout.write(self.name+" "+time.ctime()+" \n")
time.sleep(0.1)
semaphore.release()
if __name__ == "__main__":
semaphore = threading.Semaphore(2)
threadLock = threading.Lock()
list1 = []
for i in range(10):
list1.append(myThread())
for i in list1:
i.start()
执行结果
Thread-1 Thu Jan 20 23:32:43 2022
Thread-2 Thu Jan 20 23:32:43 2022
Thread-3 Thu Jan 20 23:32:43 2022
Thread-4 Thu Jan 20 23:32:43 2022
Thread-5 Thu Jan 20 23:32:43 2022
Thread-6 Thu Jan 20 23:32:43 2022
Thread-7 Thu Jan 20 23:32:43 2022
Thread-8 Thu Jan 20 23:32:43 2022
Thread-10 Thu Jan 20 23:32:43 2022
Thread-9 Thu Jan 20 23:32:43 2022
进程已结束,退出代码为 0
条件变量Condition
# !/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2022/1/18 9:34
# @Author : 波澜不惊
# @File : 条件变量Condition.py
# 条件变量就相当于一个加了条件判断的锁
# Condition通常与一个锁相关联
# 相关函数:
# acquire -线程锁,注意线程条件变量Condition中所有相关函数使用必须在acquire/release内部操作
# release -释放锁,同样,在acquire/release内部操作
# wait(timeout) -线程挂起(阻塞),直到一个notify通知或者超时才会被唤醒继续运行(超时参数默认不设置,可选填,浮点数,单位秒)
# wait必须在已经获得Lock的前提下调用,负责会触发RuntimeError
# notify(n=1) -通知其他线程,那些挂起的线程接到这个通知之后会开始运行,
# 缺省参数是通知一个正等待通知的线程,最多则唤醒n个等待的线程,
# 和wait一样,notify也要在已经获得Lock的前提下调用,否则触发RuntimeError
# 但不同的是,notify不会主动释放Lock
# notifyAll -所见即所得,通知所有线程
import ctypes
import random
import threading
import time
# 生产者与消费者例子
class Bread(object):
def __init__(self, num):
self.num = num
con = threading.Condition() # Condition条件变量对象
bread = Bread(5) # 创建对象方便全局使用,女朋友先倒了5杯放在桌子上
class Consumers(threading.Thread):
def run(self):
con.acquire() # 上锁
# con.wait() # 等待女朋友倒酒
while True:
if bread.num == 0:
print("淦!小看我的酒量吗?快倒酒!")
con.notify() # 通知女朋友启动
con.wait() # 你等着喝
else:
bread.num -= 1
print("你喝下一杯,剩下" + str(bread.num) + "杯")
time.sleep(1)
class Producer(threading.Thread):
def run(self):
con.acquire()
while True:
n = random.randint(2, 5)
bread.num += n
print("御弟哥哥,刚倒了" + str(n) + "杯,快喝吧")
time.sleep(2)
con.notify()
con.wait()
consumers = Consumers()
producer = Producer()
consumers.start()
producer.start()
执行结果
你喝下一杯,剩下4杯
你喝下一杯,剩下3杯
你喝下一杯,剩下2杯
你喝下一杯,剩下1杯
你喝下一杯,剩下0杯
淦!小看我的酒量吗?快倒酒!
御弟哥哥,刚倒了3杯,快喝吧
你喝下一杯,剩下2杯
你喝下一杯,剩下1杯
你喝下一杯,剩下0杯
淦!小看我的酒量吗?快倒酒!
御弟哥哥,刚倒了5杯,快喝吧
你喝下一杯,剩下4杯
你喝下一杯,剩下3杯
......
事件Event
举了个放学回家的例子,挺合适的
# !/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2022/1/18 9:35
# @Author : 波澜不惊
# @File : 事件Event.py
# 事件对象管理一个内部标志,通过set()方法将其设置为True,
# 使用clear()方法设置为False,wait()方法阻塞,直到标志为True
# 该标志缺省值为False
# is_set -当且仅当内部标志为True时返回True
# set -将内部标志设置为True,所有等待它称为True的线程都被唤醒,当标志为True时,wait是不会阻塞的
# clear -将内部标志重置为False,然后调用wait的线程将会阻塞
# wait -阻塞直到内部标志为True,如果调用wait时内部标志为True,则立即返回True
# wait方法总是返回True,除非设置了timeout并发生超时
import time
import threading
from sys import stdout
event = threading.Event()
class GoHome(threading.Thread):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
string1 = self.name + "收拾好书包了\n"
# time.sleep(1)
stdout.write(string1)
event.wait()
string2 = self.name + "飞快跑出教室\n"
time.sleep(1)
stdout.write(string2)
t1 = GoHome("张三")
t2 = GoHome("王五")
t3 = GoHome("李四")
t1.start()
t2.start()
t3.start()
stdout.write("ding~ding~ding~ding~~~~~~~~~~~~~~\n")
event.set()
执行结果
张三收拾好书包了
王五收拾好书包了
李四收拾好书包了
ding~ding~ding~ding~~~~~~~~~~~~~~
王五飞快跑出教室
李四飞快跑出教室
张三飞快跑出教室
进程已结束,退出代码为 0
练习
使用类继承的方式,实现信号量、事件功能操作。具体案例:第一个线程中获取当前时间,判断当前时间3秒之后,触发“事件” 对象。在另一个线程中,作为数学考试结束的判断变量,否则一直处于考试中,并打印。
# !/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2022/1/19 18:09
# @Author : 波澜不惊
# @File : 题1.py
# 使用类继承的方式,实现信号量、事件功能操作。具体案例:第一个
# 线程中获取当前时间,判断当前时间3秒之后,触发“事件” 对象。在另
# 一个线程中,作为数学考试结束的判断变量,否则一直处于考试中,并打
# 印。
import time
import threading
event = threading.Event()
semaphore = threading.Semaphore(2)
class TimeCloser(threading.Thread):
def run(self):
if semaphore.acquire():
print("现在时间是"+time.ctime())
time.sleep(3)
event.set()
semaphore.release()
class Test(threading.Thread):
def run(self):
if semaphore.acquire():
while True:
if event.is_set():
print("考试结束!")
break
else:
print("考试中")
time.sleep(0.5)
semaphore.release()
timeCloser = TimeCloser()
test = Test()
timeCloser.start()
test.start()
执行结果
现在时间是Thu Jan 20 23:37:06 2022
考试中
考试中
考试中
考试中
考试中
考试中
考试结束!
进程已结束,退出代码为 0