信号量(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" % 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("\033[41m red light is on ....\033[0m")
elif count > 10:
event.set() # 创建标志位,变成绿灯
count = 0
else:
print("\033[42m green light is on ....\033[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("\033[32m green light is on , start going ...\033[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("\033[32;1m door opening....\033[0m")
door_open_time_counter +=1 else:
print("\033[31;1m door closed...., swipe to open.\033[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("\033[34;1m door is opened, passing.....\033[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()

  

【python】-- 信号量(Semaphore)、event(红绿灯例子)的更多相关文章

  1. python lock, semaphore, event实现线程同步

    lock 机制不管你是java, C#, 还是python都是常用的线程同步机制, 相比较C# 的锁机制, python的加锁显得比较简单, 直接调用threading 标准库的lock 就可以了. ...

  2. python 信号量,Event, 定时器

    信号量 信号量也是一把锁,可以指定信号量为5,对比互斥锁同一时间只能有一个任务抢到锁去执行,信号量同一时间可以有5个任务拿到锁去执行. 如果说互斥锁是合租房屋的人去抢一个厕所,那么信号量就相当于一群路 ...

  3. Python 36 死锁现象和递归锁、信号量、Event事件、线程queue

    一:死锁现象和递归锁 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远 ...

  4. Python之网路编程之死锁,递归锁,信号量,Event事件,线程Queue

    一.死锁现象与递归锁 进程也是有死锁的 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用, 它们都将无法推进下去.此时称系统处于死锁状态或系统 ...

  5. python 管道 事件(Event) 信号量 进程池(map/同步/异步)回调函数

    ####################总结######################## 管道:是进程间通信的第二种方式,但是不推荐使用,因为管道会导致数据不安全的情况出现 事件:当我运行主进程的 ...

  6. python 多线程中的同步锁 Lock Rlock Semaphore Event Conditio

    摘要:在使用多线程的应用下,如何保证线程安全,以及线程之间的同步,或者访问共享变量等问题是十分棘手的问题,也是使用多线程下面临的问题,如果处理不好,会带来较严重的后果,使用python多线程中提供Lo ...

  7. python线程信号量semaphore(33)

    通过前面对 线程互斥锁lock /  线程事件event / 线程条件变量condition / 线程定时器timer 的讲解,相信你对线程threading模块已经有了一定的了解,同时执行多个线程的 ...

  8. 互斥锁lock、信号量semaphore、事件Event、

    1.互斥锁lock 应用在多进程中互斥所lock:互斥锁是进程间的get_ticket互相排斥进程之间,谁先枪占到资源,谁就先上锁,等到解锁之后,下一个进程在继续使用.# 语法: 上锁: lock.a ...

  9. python类库32[多进程同步Lock+Semaphore+Event]

    python类库32[多进程同步Lock+Semaphore+Event]   同步的方法基本与多线程相同. 1) Lock 当多个进程需要访问共享资源的时候,Lock可以用来避免访问的冲突. imp ...

随机推荐

  1. 2017.7.21 Linux中ELK服务后台运行方式

    通过 2017.7.18 linux下ELK环境搭建 搭建好服务于之后,一旦按下Ctrl+C或者退出登录会话,服务的进程就随之停止了.要长期在后台运行此程序,有几种方式: 1 nohup 输入Ctrl ...

  2. Cocos2d-x 3.2 大富翁游戏项目开发-第七部分 获取角色路径_2

    在编写获取路径方法前,我们先把角色须要的动画文件载入进来,角色的文件为png 和 plist格式. player1_anim.png.plist             player1_anim.pn ...

  3. MyBatis Generator生成DAO——序列化

    MyBatis Generator生成DAO 的时候,生成的类都是没有序列化的. 还以为要手工加入(開始是手工加入的),今天遇到分页的问题,才发现生成的时候能够加入插件. 既然分页能够有插件.序列化是 ...

  4. 点击Div,显示其innerHTML

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. Solidworks草图或者特征无法删除怎么办

      单击重新建模之后即可删除.

  6. 计算两个有序数组的第K大数(转)

    传统解法,最直观的解法是O(m+n).直接merge两个数组,然后求第K大的数字. 如果想要时间复杂度将为O(log(m+n)).我们可以考虑从K入手.如果我们每次能够删除一个一定在第K个元素之前的元 ...

  7. java jdk 环境变量设置

    我的电脑点右键,选择“属性”,选择“高级”标签,进入环境变量设置,分别设置如下三个环境变量: 设置JAVA_HOME: 一是为了方便引用,比如,JDK安装在C:\jdk1.6.0目录里,则设置JAVA ...

  8. trac 的安装设置

    Trac的安装设置 原网页:http://wiki.ubuntu.org.cn/Trac%E7%9A%84%E5%AE%89%E8%A3%85%E8%AE%BE%E7%BD%AE 出自Ubuntu中文 ...

  9. NB的CSS样式集锦1——CSS3滚动条美化,CSS3滚动条皮肤

    转自:http://www.pengyaou.com/codecss3/POKDNMS_112.html CSS3 -webkit-scrollbar滚动条皮肤美化实现,利用-webkit-scrol ...

  10. 改变listview中item选中时文字的颜色

    摘要 当listview的某个item选中时,默认有个选中的高亮显示,如果你要自定义选中时的高亮显示效果,可以在listview中设置属性 android:listSelector="@dr ...