信号量说白了就是控制线程并发数,是线程又先后的并发数量

请看样例:

import threading  # 导入模块
import time  # 导入模块


class Exam(threading.Thread):  # 创建类
    def __init__(self, num):  # 初始化
        super(Exam, self).__init__()  # 父类初始化
        self.num = num  # 初始化变量

    def run(self):  # 重写父类方法
        semaphore.acquire()  # 信号量获取
        print(self.num)  # 打印
        time.sleep(2)  # 延迟2秒
        semaphore.release()  # 释放信号量


if __name__ == "__main__":  # 主函数
    semaphore = threading.Semaphore(3)  # 创建实例,设置信号量为3
    for i in range(50):  # 循环50次
        exam = Exam(60)  # 创建实例
        exam.start()  # 开启线程

输出结果:

python 信号量阻塞进程 python中的信号量_python

我们发现,设置信号量之后,是每三个一组,也就是三个线程进行之后,再接下来三个再进行

条件变量(Condition):

        条件变量通常与一个锁关联。需要在多个Contidion中共享一个锁时,可以传递一个Lock/RLock实例给构造方法,否则它将自己生成一个RLock实例。可以这样理解,除了Lock带有的锁定池外,Condition还包含一个等待池,池中的线程处于状态图中的等待阻塞状态,直到另一个线程调用notify()会通知后来线程,得到通知后线程进入锁定池等待锁定,也就是一个线程的运行中可容纳另一个线程从第一个运行的半途中运行

import threading  # 导入模块
import time  # 导入模块


class Test(threading.Thread):  # 创建类
    def __init__(self, num):  # 初始化
        super(Test, self).__init__()  # 父类初始化
        self.num = num  # 初始化变量

    def run(self):  # 重写父类方法
        con.acquire()  # 获取锁
        print("线程:" + self.num)  # 打印
        con.notify()  # 通知后续线程
        print("线程" + self.num + "挂起")  # 打印
        con.wait()  # 线程挂起,知道超时或者收到notify通知
        time.sleep(2)  # 延迟2秒
        print("线程" + self.num + "再次启动")  # 打印
        con.notify()  # 通知后续线程
        con.release()  # 释放锁


class Test2(threading.Thread):
    def __init__(self, num2):
        super(Test2, self).__init__()
        self.num2 = num2

    def run(self):
        con.acquire()  # 获取锁
        print("线程:" + self.num2)  # 打印
        con.notify()  # 通知后续线程
        print("线程" + self.num2 + "挂起")  # 打印
        con.wait()  # 线程挂起,知道超时或者收到notify通知
        time.sleep(2)  # 延迟2秒
        print("线程" + self.num2 + "再次启动")  # 打印
        con.notify()  # 通知后续线程
        con.release()  # 释放锁


if __name__ == "__main__":  # 主函数
    con = threading.Condition()  # 创建条件变量实例
    t1 = Test(str(1))  # 创建实例
    t1.start()  # 开启线程
    t2 = Test2(str(2))  # 创建实例
    t2.start()  # 开启线程

输出结果

python 信号量阻塞进程 python中的信号量_python_02

 可见线程1启动后会通知线程2启动,随后线程1挂起,然后线程2启动,随后通知线程1,然后线程2挂起,接着线程1再次启动,然后通知线程2再次启动,这便是条件变量的运行原理。

事件:

import threading  # 导入模块
import time  # 导入模块


class Test(threading.Thread):  # 创建类
    def __init__(self):  # 初始化
        super(Test, self).__init__()  # 父类初始化
        # self.num = num  # 初始化变量

    def run(self):  # 重写父类方法
        while True:  # 无限循环
            if event.is_set():  # 判断是否设置事件
                print("事件触发")  # 打印
            else:  # 否定
                print("事件停止")  # 打印
                event.wait()  # 等待事件停止3秒


class Test2(threading.Thread):  # 创建类
    def __init__(self, ):  # 初始化
        super(Test2, self).__init__()  # 父类初始化
        # self.num2 = num2

    def run(self):  # 重写分类方法
        while True:  # 无限循环
            event.set()  # 设置事件
            time.sleep(1)  # 延迟1秒
            event.clear()  # 清除事件
            time.sleep(3)  # 延迟3秒


if __name__ == "__main__":  # 主函数
    event = threading.Event()  # 创建时间实例
    t1 = Test()  # 创建实例
    t1.start()  # 开启线程
    t2 = Test2()  # 创建实例
    t2.start()  # 开启线程

输出结果:

python 信号量阻塞进程 python中的信号量_开发语言_03

开间当if判断检测到设置事件后,会打印“事件触发”,然后延迟一秒,但程序还会检测事件是否仍存在,当延迟时,事件的确存在,所以会一直打印,当事件清除(clear方法)后,程序检测到事件被清除了,所以打印“事件停止”,延迟3秒,有序程序是无限循环的,所以会继续重新创建事件,周而复始,一直持续整个重复过程。