条件变量同步

有一类线程需要满足条件之后才能够继续执行,Python提供了threading.Condition 对象用于条件变量线程的支持,它除了能提供RLock()或Lock()的方法外,还提供了 wait()、notify()、notifyAll()方法。

lock_con=threading.Condition([Lock/Rlock]): 锁是可选选项,不传人锁,对象自动创建一个RLock()。

wait():条件不满足时调用,线程会释放锁并进入等待阻塞;
notify():条件创造后调用,通知等待池激活一个线程;
notifyAll():条件创造后调用,通知等待池激活所有线程。
import threading, time
from random import randint class Producer(threading.Thread):
def run(self):
global L
while True:
val = randint(0, 100)
print('生产者', self.name, ':Append'+str(val),L)
if lock_con.acquire():
L.append(val)
lock_con.notify()
lock_con.release()
time.sleep(3) class Consumer(threading.Thread):
def run(self):
global L
while True:
lock_con.acquire()
if len(L) == 0:
lock_con.wait()
print('消费者', self.name, ":Delete" + str(L[0]), L)
del L[0]
lock_con.release()
time.sleep(0.25) if __name__ == "__main__":
L = []
lock_con = threading.Condition()
threads = []
for i in range(5):
threads.append(Producer())
threads.append(Consumer())
for t in threads:
t.start()
for t in threads:
t.join()
print('---- end ----') #运行结果:
生产者 Thread-1 :Append63 []
生产者 Thread-2 :Append66 [63]
生产者 Thread-3 :Append20 [63, 66]
生产者 Thread-4 :Append83 [63, 66, 20]
生产者 Thread-5 :Append2 [63, 66, 20, 83]
生产者 Thread-4 :Append26 []
消费者 Thread-6 :Delete26 [26]
生产者 Thread-2 :Append21 []
生产者 Thread-3 :Append71 [21]
生产者 Thread-1 :Append19 [21, 71]
生产者 Thread-5 :Append100 [21, 71, 19]
生产者 Thread-1 :Append96 []
消费者 Thread-6 :Delete96 [96]
........

同步条件

条件同步和条件变量同步差不多意思,只是少了锁功能,因为条件同步设计于不访问共享资源的条件环境。event=threading.Event():条件环境对象,初始值 为False;

event.isSet():返回event的状态值;
event.wait():如果 event.isSet()==False将阻塞线程;
event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;
event.clear():恢复event的状态值为False。
import threading, time

class Boss(threading.Thread):
def run(self):
print("BOSS: 今晚大家加班")
event.isSet() or event.set()
time.sleep(5)
print("BOSS: 大家可以下班了")
event.isSet() or event.set() class Worker(threading.Thread):
def run(self):
event.wait()
print("Worker: 唉。。。。")
time.sleep(0.25)
event.clear()
event.wait()
print("Worker: Great!") if __name__ == "__main__":
event = threading.Event()
threads = []
for i in range(5):
threads.append(Worker())
threads.append(Boss())
for t in threads:
t.start()
for t in threads:
t.join() #运行结果:
BOSS: 今晚大家加班
Worker: 唉。。。。
Worker: 唉。。。。
Worker: 唉。。。。
Worker: 唉。。。。
Worker: 唉。。。。
BOSS: 大家可以下班了
Worker: Great!
Worker: Great!
Worker: Great!
Worker: Great!
Worker: Great!

列队

q = Queue.Queue(maxsize = 10) 创建一个“队列”对象。Queue.Queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过Queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。

q.put()方法在队尾插入一个项目。put()有两个参数,第一个item为必需的,为插入项目的值;第二个block为可选参数,默认为1。如果队列当前为空且block为1,put()方法就使调用线程暂停,直到空出一个数据单元。如果block为0,put方法将引发Full异常。

q.get([block[, timeout]])方法从队头删除并返回一个项目。可选参数为block,默认为True。如果队列为空且block为True,get()就使调用线程暂停,直至有项目可用。如果队列为空且block为False,队列将引发Empty异常,timeout等待时间。

q.qsize() 返回队列的大小
q.empty() 如果队列为空,返回True,反之False
q.full() 如果队列满了,返回True,反之False
q.full 与 maxsize 大小对应
q.get_nowait() 相当q.get(False)
q.put_nowait(item) 相当q.put(item, False)
q.task_done() 在完成一项工作之后,q.task_done() 函数向任务已经完成的队列发送一个信号
q.join() 实际上意味着等到队列为空,再执行别的操作
import queue

d = queue.Queue()

d.put('1')
d.put('2')
d.put('3') print(d.get())
print(d.get())
print(d.get())
print(d.get())
print(d.get(0)) # 运行结果:
1
2
3
报错:
queue.Empty

线程操作列表是不安全的。

import threading, time

li = [1, 2, 3, 4, 5]

def pri():
while li:
a = li [-1]
print(a)
time.sleep(1)
try:
li.remove(a)
except:
print('-----', a)
t1 = threading.Thread(target=pri, args=())
t1.start()
t2 = threading.Thread(target=pri, args=())
t2.start() # 运行结果:
5
5
4
----- 5
4
3
----- 4
3
2
----- 3
2
1
----- 2
1
----- 1
import threading, queue
from time import sleep
from random import randint class Production(threading.Thread):
def run(self):
while True:
r = randint(0, 100)
q.put(r)
print("生产出来 %s 号包子" %r)
sleep(1) class Proces(threading.Thread):
def run(self):
while True:
re = q.get()
print('吃掉 %s号包子' %re) if __name__ == '__main__':
q = queue.Queue(10)
threads = [Production(),Production(),Production(),Proces()]
for t in threads:
t.start() # 运行结果:
生产出来 94 号包子
生产出来 13 号包子
生产出来 79 号包子
吃掉 94号包子
吃掉 13号包子
吃掉 79号包子
生产出来 43 号包子
吃掉 43号包子
生产出来 32 号包子
吃掉 32号包子
......

Python 线程同步变量,同步条件,列队的更多相关文章

  1. python线程中的同步问题

    多线程开发可能遇到的问题 假设两个线程t1和t2都要对num=0进行增1运算,t1和t2都各对num修改1000000次,num的最终的结果应该为2000000.但是由于是多线程访问,有可能出现下面情 ...

  2. python 线程之 数据同步 Queue

    Queue:将数据从一个线程发往另外一个线程比较通用的方式是使用queue模块的Queue类 1, 首先创建一个Queue模块的对象,创建Queue对象可以传递maxsize也可以不传递 2. 使用对 ...

  3. python初识,变量,条件判断语句,基本数据类型,while循环语句

    python文件后缀可以是任意,但是导入模块时不用.py后缀时会报错 python文件的两种执行方式: python解释器 python文件路径 进入python解释权,事实获取执行结果 在Linux ...

  4. Python学习---线程锁/信号量/条件变量同步/线程池1221

    线程锁 问题现象: 多线程情况下,CPU遇到阻塞会进行线程的切换,所以导致执行了tmp-=1的值还未赋值给num=tmp,另一个线程2又开始了tmp -=1,所以导致最后的值重复赋值给了num,所以出 ...

  5. 练习生产者与消费者-PYTHON多线程中的条件变量同步-Queue

    以前练习过,但好久不用,手生,概念也生了, 重温一下.. URL: http://www.cnblogs.com/holbrook/tag/%E5%A4%9A%E7%BA%BF%E7%A8%8B/ ~ ...

  6. PYTHON线程知识再研习E---条件变量同步Condition

    Python提供的Condition对象提供了对复杂线程同步问题的支持.Condition被称为条件变量,除了提供与Lock类似的 acquire和release方法外,还提供了wait和notify ...

  7. python多线程编程5: 条件变量同步-乾颐堂

    互斥锁是最简单的线程同步机制,Python提供的Condition对象提供了对复杂线程同步问题的支持.Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还 ...

  8. 27 python 初学(信号量、条件变量、同步条件、队列)

    参考博客: www.cnblogs.com/yuanchenqi/articles/5733873.html  semaphore 信号量: condition 条件变量: event 同步条件:条件 ...

  9. Linux 多线程条件变量同步

    条件变量是线程同步的另一种方式,实际上,条件变量是信号量的底层实现,这也就意味着,使用条件变量可以拥有更大的自由度,同时也就需要更加小心的进行同步操作.条件变量使用的条件本身是需要使用互斥量进行保护的 ...

随机推荐

  1. SharkApktool 源码攻略

    作者:HAI_ 原文来自:https://bbs.ichunqiu.com/thread-43219-1-1.html 0×00 前言 网上的资料对于apktool的源码分析,来来回回就那么几个,而且 ...

  2. 机器学习技法笔记:12 Neural Network

    Roadmap Motivation Neural Network Hypothesis Neural Network Learning Optimization and Regularization ...

  3. 使用create-react-app 快速构建 React 开发环境以及react-router 4.x路由配置

    create-react-app 是来自于 Facebook,通过该命令我们无需配置就能快速构建 React 开发环境. create-react-app 自动创建的项目是基于 Webpack + E ...

  4. 算法手记(2)Dijkstra双栈算术表达式求值算法

    这两天看到的内容是关于栈和队列,在栈的模块发现了Dijkstra双栈算术表达式求值算法,可以用来实现计算器类型的app. 编程语言系统一般都内置了对算术表达式的处理,但是他们是如何在内部实现的呢?为了 ...

  5. JAVA中的COPYONWRITE容器

    Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改, ...

  6. 源码编译安装lnmp环境

    一.源码编译安装步骤 首先说明源码安装的好处   速度快,可自定义路径 主要有三步:1.配置 进入源码安装包  ./configure --prefix=/uer/local/nginx  可指定参数 ...

  7. EasyNetQ中使用自定义的ISerializer

    最近在使用EasyNetQ时,遇到一个问题:c++项目组发送的消息数据不是Json数据,而是自定义的数据格式(各字段+‘|’连接成一个字符串),EasyNetQ中消费消息接收的都是强类型,没办法直接消 ...

  8. Python编码和Unicode

    原文链接: ERIC MORITZ   翻译: 伯乐在线- 贱圣OMG译文链接: http://blog.jobbole.com/50345/ 我确定有很多关于Unicode和Python的说明,但为 ...

  9. 如何在IDEA里给大数据项目导入该项目的相关源码(博主推荐)(类似eclipse里同一个workspace下单个子项目存在)(图文详解)

    不多说,直接上干货! 如果在一个界面里,可以是单个项目 注意:本文是以gradle项目的方式来做的! 如何在IDEA里正确导入从Github上下载的Gradle项目(含相关源码)(博主推荐)(图文详解 ...

  10. DP的学习

    DP在ACM的算法里面可算是重中之重,题目类型千变万化,题目难度差异也很大.是一种很讲究技巧的算法,而且代码实现相对容易,1y率非常高(除有些bt数据外).总之DP就是一向非常重要,又非常博大精深的算 ...