• 【python】-- 信号量(Semaphore)、event(红绿灯例子)


    信号量(Semaphore)

    之前讲的线程锁(互斥锁) 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。

    1、信号量

    1. 是一个变量,控制着对公共资源或者临界区的访问。信号量维护着一个计数器,指定可同时访问资源或者进入临界区的线程数。 
    2. 每次有一个线程获得信号量时,计数器-1。若计数器为0,其他线程就停止访问信号量,直到另一个线程释放信号量

    说白了就是在同一时间,可以只允许设定的数量的线程去执行

    import threading
    import time
    
    
    def run(n):
        semaphore.acquire()   # 加信号量锁
        time.sleep(5)
        print("run the thread: %s
    " % n)
        semaphore.release()   # 释放信号量锁
    
    
    if __name__ == '__main__':
    
        semaphore = threading.BoundedSemaphore(5)  # 最多允许5个线程同时运行(Bounded:绑定,Semaphore:信号量)
        for i in range(20):
            t = threading.Thread(target=run, args=(i,))
            t.start()
    
    while threading.active_count() != 1:
        pass
    else:
        print('----all threads done---')
    

    上面程序的执行,会让人感觉是:分了4组,前5个同时完成,然后又5个同时进去。但是实际的效果是:这5个里面如果有3个完成,就会立刻再放3个进去。不会等5个都完成,每出来1个就放进去1个,出来几个放进去几个

    2、使用场景和总结

    1. 连接池,线程池,MySQL的有连接池,同一时间有多少个并发,就能连多少个连接。
    2. 我们为了保证我的socket_server,因为python不会默认现在你启动多少个线程,但是你启动的线程越多,就会把系统拉的越慢,就会把程序拉的越慢。这里就可以搞一个我同一时间放100线程个进来,就是用semaphore
    3. python3.x 虽然不加锁也是正确的,但是最好还是把锁加上

    event(红绿灯例子)

    日常生活中经常遇到红绿灯,我们就很好理解红绿灯的例子,就是红灯停,绿灯行。

      现在生成一个线程,这个线程我让它扮演红绿灯,它每过一段时间就变成绿灯,又过一段时间变成红灯,又变成黄灯。然后再生成3-5个线程作为车。车看见红灯,它就停下来等着,如果说是绿灯,车子就走。所以就涉及到红灯这个线程,红绿灯的这个线程就跟车线程之前产生了依赖了。就是红绿灯这个线程必须在绿灯的时候才能走,在红灯的时候就立刻停下来。所以互相之前,一个线程会根据另外一个线程的状态产生一些变化。类似这种场景的实现,就是:event,即事件。

    1、事件的基础内置函数

    event = threading.Event()   # 设置一个事件的全局变量
    
    event.is_set()# 判断是否已经设置标志位。
    
    event.wait()   # 没有设置标志位的时候会阻塞,一遇到标志位就不会阻塞 #判断是否已经设置标志位。
    
    event.set()   # 设置标志位 ,标志位设置了,代表着绿灯,直接通行。
    
    event.clear()   # 清除标志位,标志位被清空,代表红灯,wait等待变绿灯。
    

    2、红绿灯例子

    import threading
    import time
    
    event = threading.Event()  # 生成线程事件实例
    
    
    def lighter():
        """
        模拟红绿灯
        :return:
        """
        count = 0
        event.set()   # 先设置标志位,代表绿灯
        while True:
            if count > 5 and count < 10:   # 改成红灯
                event.clear()    # 清除标志位,变成红灯
                print("33[41m red light is on ....33[0m")
            elif count > 10:
                event.set()   # 创建标志位,变成绿灯
                count = 0
            else:
                print("33[42m green light is on ....33[0m")
    
            time.sleep(1)
            count += 1
    
    
    def car(name):
        """
        模拟车子
        :param name:
        :return:
        """
        while True:
            if event.is_set():   # 有标志位,代表是绿灯
                print("{0} running ....".format(name))
                time.sleep(1)
            else:   # 如果不是绿灯就代表红灯
                print("{0} sees red light ,waiting ....".format(name))
                event.wait()   # 阻塞
                print("33[32m green light is on , start going ...33[0m")
    
    
    light = threading.Thread(target=lighter,)  # 启动代表红绿灯的线程
    light.start()
    
    car1 = threading.Thread(target=car, args=("car1",))  # 启动代表车的线程
    car1.start()
    

    3、员工刷卡例子

    员工进公司门要刷卡, 我们这里设置一个线程是“门”, 再设置几个线程为“员工”,员工看到门没打开,就刷卡,刷完卡,门开了,员工就可以通过。

    import threading
    import time
    import random
    
    
    def door():
        door_open_time_counter = 0
        while True:
            if door_swiping_event.is_set():
                print("33[32;1m door opening....33[0m")
                door_open_time_counter +=1
    
            else:
                print("33[31;1m door closed...., swipe to open.33[0m")
                door_open_time_counter = 0  # 清空计时器
                door_swiping_event.wait()
    
            if door_open_time_counter > 3:  # 门开了已经3s了,该关了
                door_swiping_event.clear()
    
            time.sleep(0.5)
    
    
    def staff(n):
    
        print("staff [%s] is coming..." % n )
        while True:
            if door_swiping_event.is_set():
                print("33[34;1m door is opened, passing.....33[0m")
                break
            else:
                print("staff [%s] sees door got closed, swiping the card....." % n)
                print(door_swiping_event.set())
                door_swiping_event.set()
                print("after set ", door_swiping_event.set())
            time.sleep(0.5)
    
    
    if __name__ == "__main__":
    
        door_swiping_event = threading.Event()  # 设置事件
        door_thread = threading.Thread(target=door)
        door_thread.start()
    
        for i in range(20):
            p = threading.Thread(target=staff, args=(i,))
            time.sleep(random.randrange(3))
            p.start()
    

      

  • 相关阅读:
    《JavaScript 闯关记》之初探
    《JavaScript 闯关记》之简介
    《JavaScript 闯关记》
    JavaScript检测之basevalidate.js
    如何排版 微信公众号「代码块」
    android开发之路03
    android开发之路02(浅谈BroadcastReceiver)
    android开发之路01
    软件工程复习(一)
    软件工程—人件(一)
  • 原文地址:https://www.cnblogs.com/Keep-Ambition/p/7597310.html
Copyright © 2020-2023  润新知