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的更多相关文章

  1. 并发编程(五)——GIL全局解释器锁、死锁现象与递归锁、信号量、Event事件、线程queue

    GIL.死锁现象与递归锁.信号量.Event事件.线程queue 一.GIL全局解释器锁 1.什么是全局解释器锁 GIL本质就是一把互斥锁,相当于执行权限,每个进程内都会存在一把GIL,同一进程内的多 ...

  2. TCP协议下的服务端并发,GIL全局解释器锁,死锁,信号量,event事件,线程q

    TCP协议下的服务端并发,GIL全局解释器锁,死锁,信号量,event事件,线程q 一.TCP协议下的服务端并发 ''' 将不同的功能尽量拆分成不同的函数,拆分出来的功能可以被多个地方使用 TCP服务 ...

  3. Python中的函数对象与闭包

    函数在Python中是第一类对象,可以当做参数传递给其他函数,放在数据结构中,以及作为函数的返回结果. 下面的例子为接受另外一个函数作为输入并调用它 #foo.py def callf(func): ...

  4. Python中的可变对象和不可变对象

    Python中的可变对象和不可变对象 什么是可变/不可变对象 不可变对象,该对象所指向的内存中的值不能被改变.当改变某个变量时候,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一 ...

  5. 《python解释器源码剖析》第4章--python中的list对象

    4.0 序 python中的list对象,底层对应的则是PyListObject.如果你熟悉C++,那么会很容易和C++中的list联系起来.但实际上,这个C++中的list大相径庭,反而和STL中的 ...

  6. 全面了解python中的类,对象,方法,属性

    全面了解python中的类,对象,方法,属性 python中一切皆为对象,所谓对象:我自己就是一个对象,我玩的电脑就是对象,坐着的椅子就是对象,家里养的小狗也是一个对象...... 我们通过描述属性( ...

  7. 【Python核心编程笔记】一、Python中一切皆对象

    Python中一切皆对象 本章节首先对比静态语言以及动态语言,然后介绍 python 中最底层也是面向对象最重要的几个概念-object.type和class之间的关系,以此来引出在python如何做 ...

  8. python中一切皆对象的理解

    一切皆对象? 学过Java都知道,Java中有8个基本类型,其余的都是继承自Object类的引用类型.方法内的基本类型变量会在栈上分配,而引用类型会通过逃逸分析来决定在栈上分配或堆上分配.Java中关 ...

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

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

随机推荐

  1. Pollard's Rho算法简单总结

    先贴一份代码在这. 最近几天实在是太忙了没时间更新了. 代码 #include <iostream> #include <cstdio> #include <cstdli ...

  2. Java连接Oracle数据库常用方法

    JDBC的六大步骤: 注册驱动 获取连接 获取执行sql语句对象 执行sql语句 处理结果集 关闭资源 oracle URL: jdbc:oracle:thin:@localhost:1521:SID ...

  3. sqli-labs(29)

    0X01 题目说有waf 那我们先来试探一波 ?id=-' union select 1,database(),3%23 成功了 那么他的WAF过滤了什么呐? 这是index.php的源码并没有过滤什 ...

  4. (转载)Kaggle_Titanic生存预测 -- 详细流程吐血梳理

    Kaggle_Titanic生存预测 -- 详细流程吐血梳理 https://blog.csdn.net/Koala_Tree/article/details/78725881 Kaggle中Tita ...

  5. legend3---2、网站的代码里面的/也是代表根目录

    legend3---2.网站的代码里面的/也是代表根目录 一.总结 一句话总结: 不过这个根目录在public下面 1.mysql删除数据库命令? drop database <数据库名> ...

  6. always_populate_raw_post_data

    Deprecated: Automatically populating $HTTP_RAW_POST_DATA is deprecated and will be removed in a futu ...

  7. Python 字符串与列表去重

    最近面试中出现频率比较高的字符串和列表的去重pstr = 'abcadcf'# 字符串去重# 1.使用集合 --没有保持原来的顺序 print(set(pstr)) # 2.使用字典 -- 没有保持原 ...

  8. autoprefixer不起作用的坑

    概述 今天同事说,nuxt.js的项目好像没有自动加前缀,我花了很长时间查找原因,最后终于发现,原来是没有加.browserslistrc文件...记录下来,供以后开发时参考,相信对其他人也有用. b ...

  9. ApplicationSettingsBase运用

    先建一个类继承于ApplicationSettingsBase using System; using System.ComponentModel; namespace Concert.Configu ...

  10. 阶段3 1.Mybatis_06.使用Mybatis完成DAO层的开发_7 Mybatis中使用代理Dao的执行过程分析

    另外一种情况,不写Mybits的dao实现类的情况. 切换工程到CRUD的工程.这里面是不写dao实现类的方式 进入到GetMaper里面.这里是创建代理对象 去找SqlSession的实现类Defa ...