Python 中Semaphore 信号量对象、Event事件、Condition
Semaphore 信号量对象
信号量是一个更高级的锁机制。信号量内部有一个计数器而不像锁对象内部有锁标识,而且只有当占用信号量的线程数超过信号量时线程才阻塞。这允许了多个线程可以同时访问相同的代码区。
Semaphore管理一个内置的计数器,每当调用acquire()时内置计数器-1;调用release() 时内置计数器+1;
计数器不能小于0;当计数器为0时,acquire()将阻塞线程直到其他线程调用release()。
直接上代码,我们把semaphore控制为3,也就是说,同时有3个线程可以用这个锁,剩下的线程也之只能是阻塞等待。
# coding:utf-8
import time
import threading
semaphore = threading.Semaphore(3)
def func():
if semaphore.acquire():
print (threading.currentThread().getName() + '获取锁')
time.sleep(5)
semaphore.release()
print (threading.currentThread().getName() + '释放锁')
for i in range(10):
t1 = threading.Thread(target=func)
t1.start()
Thread-1获取锁
Thread-2获取锁
Thread-3获取锁
Thread-3释放锁
Thread-2释放锁
Thread-4获取锁
Thread-5获取锁
Thread-1释放锁
Thread-6获取锁
Thread-6释放锁
Thread-7获取锁
Thread-4释放锁
Thread-8获取锁
Thread-5释放锁
Thread-9获取锁
Thread-8释放锁
Thread-10获取锁
Thread-7释放锁
Thread-9释放锁
Thread-10释放锁
Event事件
Event内部包含了一个标志位,初始的时候为false。
可以使用使用set()来将其设置为true;
或者使用clear()将其从新设置为false;
可以使用is_set()来检查标志位的状态;
另一个最重要的函数就是wait(timeout=None),用来阻塞当前线程,直到event的内部标志位被设置为true或者timeout超时。如果内部标志位为true则wait()函数理解返回。
# coding:utf-8
import threading
import time
event = threading.Event()
def service():
print('开启服务')
event.wait() # 括号里可以带数字执行,数字表示等待的秒数,不带数字表示一直阻塞状态
print('服务开启成功')
def start():
time.sleep(3)
print('开始执行业务')
time.sleep(3)
event.set() # 默认为False,set一次表示True,所以子线程里的foo函数解除阻塞状态继续执行
def conn():
while True:
if event.is_set() == False:
print('数据库连接成功')
time.sleep(1)
event.set()
event.wait()
break
t = threading.Thread(target=service, args=()) # 子线程执行foo函数
t.start()
t2 = threading.Thread(target=start, args=()) # 子线程执行start函数
t2.start()
t3 = threading.Thread(target=conn, args=()) # 子线程执行do函数
t3.start()
开启服务
数据库连接成功
服务开启成功
开始执行业务
Condition
可以把Condition理解为一把高级的琐,它提供了比Lock, RLock更高级的功能,允许我们能够控制复杂的线程同步问题。threadiong.Condition在内部维护一个琐对象(默认是RLock),可以在创建Condigtion对象的时候把琐对象作为参数传入。Condition也提供了acquire, release方法,其含义与琐的acquire, release方法一致,其实它只是简单的调用内部琐对象的对应的方法而已。Condition还提供了如下方法(特别要注意:这些方法只有在占用琐(acquire)之后才能调用,否则将会报RuntimeError异常。):
Condition.wait([timeout]):
wait方法释放内部所占用的琐,同时线程被挂起,直至接收到通知被唤醒或超时(如果提供了timeout参数的话)。当线程被唤醒并重新占有琐的时候,程序才会继续执行下去。
Condition.notify():
唤醒一个挂起的线程(如果存在挂起的线程)。注意:notify()方法不会释放所占用的琐。
Condition.notify_all()
Condition.notifyAll()
唤醒所有挂起的线程(如果存在挂起的线程)。注意:这些方法不会释放所占用的琐。
以下为生产者消费者模式示例:
# coding:utf-8
from threading import Thread, Condition
import time
import random
queue = []
MAX_NUM = 10
condition = Condition()
class ProducerThread(Thread):
def run(self):
nums = range(5)
global queue
while True:
condition.acquire()
if len(queue) == MAX_NUM:
print ("Queue full, producer is waiting")
condition.wait()
print ("Space in queue, Consumer notified the producer")
num = random.choice(nums)
queue.append(num)
print ("Produced", num)
condition.notify()
condition.release()
time.sleep(random.random())
class ConsumerThread(Thread):
def run(self):
global queue
while True:
condition.acquire()
if not queue:
print ("Nothing in queue, consumer is waiting")
condition.wait()
print ("Producer added something to queue and notified the consumer")
num = queue.pop(0)
print ("Consumed", num)
condition.notify()
condition.release()
time.sleep(random.random())
ProducerThread().start()
ConsumerThread().start()
Python 中Semaphore 信号量对象、Event事件、Condition的更多相关文章
- 并发编程(五)——GIL全局解释器锁、死锁现象与递归锁、信号量、Event事件、线程queue
GIL.死锁现象与递归锁.信号量.Event事件.线程queue 一.GIL全局解释器锁 1.什么是全局解释器锁 GIL本质就是一把互斥锁,相当于执行权限,每个进程内都会存在一把GIL,同一进程内的多 ...
- TCP协议下的服务端并发,GIL全局解释器锁,死锁,信号量,event事件,线程q
TCP协议下的服务端并发,GIL全局解释器锁,死锁,信号量,event事件,线程q 一.TCP协议下的服务端并发 ''' 将不同的功能尽量拆分成不同的函数,拆分出来的功能可以被多个地方使用 TCP服务 ...
- Python中的函数对象与闭包
函数在Python中是第一类对象,可以当做参数传递给其他函数,放在数据结构中,以及作为函数的返回结果. 下面的例子为接受另外一个函数作为输入并调用它 #foo.py def callf(func): ...
- Python中的可变对象和不可变对象
Python中的可变对象和不可变对象 什么是可变/不可变对象 不可变对象,该对象所指向的内存中的值不能被改变.当改变某个变量时候,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一 ...
- 《python解释器源码剖析》第4章--python中的list对象
4.0 序 python中的list对象,底层对应的则是PyListObject.如果你熟悉C++,那么会很容易和C++中的list联系起来.但实际上,这个C++中的list大相径庭,反而和STL中的 ...
- 全面了解python中的类,对象,方法,属性
全面了解python中的类,对象,方法,属性 python中一切皆为对象,所谓对象:我自己就是一个对象,我玩的电脑就是对象,坐着的椅子就是对象,家里养的小狗也是一个对象...... 我们通过描述属性( ...
- 【Python核心编程笔记】一、Python中一切皆对象
Python中一切皆对象 本章节首先对比静态语言以及动态语言,然后介绍 python 中最底层也是面向对象最重要的几个概念-object.type和class之间的关系,以此来引出在python如何做 ...
- python中一切皆对象的理解
一切皆对象? 学过Java都知道,Java中有8个基本类型,其余的都是继承自Object类的引用类型.方法内的基本类型变量会在栈上分配,而引用类型会通过逃逸分析来决定在栈上分配或堆上分配.Java中关 ...
- Python 36 死锁现象和递归锁、信号量、Event事件、线程queue
一:死锁现象和递归锁 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远 ...
随机推荐
- c#翻页效果
用c#和GDI+实现杂志翻页动画效果时间:2010-01-13 blog.csdn.net 周公 - 说明:以前本人参与个一个电子杂志项目,当时要求实现模拟现实生活中的杂志翻页动画效果,别人推荐了这篇 ...
- BZOJ 2281 Luogu P2490 [SDOI2011]黑白棋 (博弈论、DP计数)
怎么SDOI2011和SDOI2019的两道题这么像啊..(虽然并不完全一样) 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?i ...
- [BZOJ2987]Earthquake:类欧几里得算法
分析 类欧的式子到底是谁推的啊怎么这么神仙啊orz! 简单说一下这道题,题目中的约束条件可以转化为: \[ y \leq \frac{c-ax}{b} \] 有负数怎么办啊?转化一下: \[ y \l ...
- Oracle报Ora01522
应用服务报错截图 数据库后台日志报错截图 从日志分析应该是回滚异常造成表空间无法使用回滚段,而回滚涉及的表空间为undo表空间 尝试新建UNDO表空间,再将UNDO_TABLESPACE切换到新建的U ...
- 20165218 《网络对抗技术》 Exp8 Web基础
Exp8 Web基础 基础问题回答 (1)什么是表单 表单可以收集用户的信息和反馈意见,是网站管理者与浏览者之间沟通的桥梁. 一个表单有三个基本组成部分: 表单标签 表单域:包含了文本框.密码框.隐藏 ...
- AI-人工智能/机器学习 seetafaceJNI
基于中科院seetaface2进行封装的JAVA人脸识别库,支持人脸识别.1:1比对.1:N比对. 项目介绍 基于中科院seetaface2进行封装的JAVA人脸识别算法库,支持人脸识别.1:1比对. ...
- LeetCode_1116.打印零与奇偶数(多线程)
LeetCode_1116 LeetCode-1116.打印零与奇偶数 假设有这么一个类: class ZeroEvenOdd { public ZeroEvenOdd(int n) { ... } ...
- 数据结构和算法(Java版)快速学习(交换、选择、插入排序)
基本排序算法:交换.选择.插入排序 常用的交换排序又称之为:冒泡排序 一般河水中的冒泡,水底刚冒出来的时候是比较小的,随着慢慢向水面浮起会逐渐增大,冒泡排序由此物理规律得来. 冒泡算法的运作规律如下: ...
- JavaScript对象---递归遍历对象
JavaScript 中的所有事物都是对象:字符串.数值.数组.函数... 此外,JavaScript 允许自定义对象. JavaScript 对象 JavaScript 提供多个内建对象,比如 St ...
- (转)深入理解Java:注解(Annotation)自定义注解入门
向作者致敬! 转自:http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 要深入学习注解,我们就必须能定义自己的注解,并使用注解,在 ...