代码:

# -*- coding: utf-8 -*-
"""
学习线程同步,使用条件变量
逻辑:
生产消费者模型
一个有3个大小的产品库,一个生产者负责生产,一个消费者负责消费
每次生产或消费一个产品,产品库满了,生产者必须等待,产品库空了,消费者必须等待
生产者的速度是消费者的速度2倍,先启动消费者,一段时间后启动生产者 总结:
1. 条件变量底层用到R锁,对于已经获得锁的线程可以执行多次 acquire(),锁多次
2. 不确定是否和java的这一套 ,原理一样 使用:
1. 创建条件对象 cond = threading.Condition()
2. 在子线程调用 申请获取锁 cond.acquire()
3. 在程序中如果有必要 使用 cond.wait() cond.notify() cond.notifyall()
4. 使用完后 释放锁 cond.release() 参考: """
import threading
import time class Goods:
""" 记录产品数,最多3个产品
被多线程操作
"""
def __init__(self):
self.count = 0 def add(self,num = 1):
self.count += num def sub(self):
if self.count>=0:
self.count -= 1 def empty(self):
return self.count <= 0 def full(self):
return self.count >= 3 class Producer(threading.Thread):
""" 生产者
"""
def __init__(self,condition,goods,name, sleeptime=1):
threading.Thread.__init__(self)
self.cond = condition
self.goods = goods
self.sleeptime = sleeptime
self.name = name def run(self):
cond = self.cond
goods = self.goods while True:
print "p1"
cond.acquire() # 获取锁
print "p2" while goods.full(): # 如果产品满了
print "p3"
cond.wait()
print cond._Condition__lock
print "p4" print "p5"
goods.add()
print("num:",goods.count,"producer") cond.notifyAll() # 唤醒所有等待的线程,并没有交出锁
print cond._Condition__lock # 锁还在
print "p6" cond.release() # 解锁资源
print cond._Condition__lock # 锁不在了
print "p7" time.sleep(self.sleeptime) class Consumer(threading.Thread):
""" 消费者
"""
def __init__(self,condition,goods,name, sleeptime=2):
threading.Thread.__init__(self)
self.cond = condition
self.goods = goods
self.sleeptime = sleeptime
self.name = name def run(self):
cond = self.cond
goods = self.goods while True:
print "c1"
cond.acquire() # 获取锁
print "c2" while goods.empty(): # 如果没有产品了
print "c3"
cond.wait() # 执行它,交出锁,进入等待池,然后阻塞,直到被唤醒
print cond._Condition__lock # 执行到这里,继续获得了锁
print "c4" print "c5"
goods.sub()
print("num:",goods.count, "consumer") cond.notifyAll() # 唤醒所有等待的线程,并没有交出锁
print cond._Condition__lock # 锁还在
print "c6" cond.release() # 解锁资源
print cond._Condition__lock # 锁不在了
print "c7" time.sleep(self.sleeptime) if __name__ == '__main__':
g = Goods() # 共享数据
cond = threading.Condition() # 条件判断 # 启动消费者
consumer = Consumer(cond,g, name="consumer")
consumer.start() # 2秒后启动生产者
time.sleep(2) print "m1" # 启动生产者
producer = Producer(cond,g, name="producer")
producer.start() print "m2"

2 输出:

D:\Programs\Anaconda\python.exe D:/1_practice/python/projects/downloads_modify/归类/并发/thread_sync_5.py
c1
c2
c3
m1
p1m2 p2
p5
('num:', 1, 'producer')
<_RLock owner='producer' count=1>
p6
<_RLock owner=None count=0><_RLock owner='consumer' count=1> p7c4 c5
('num:', 0, 'consumer')
<_RLock owner='consumer' count=1>
c6
<_RLock owner=None count=0>
c7
p1
p2
p5
('num:', 1, 'producer')
<_RLock owner='producer' count=1>
p6
<_RLock owner=None count=0>
p7
p1
p2
p5
('num:', 2, 'producer')
<_RLock owner='producer' count=1>
p6
<_RLock owner=None count=0>
p7
c1
c2
c5
('num:', 1, 'consumer')
<_RLock owner='consumer' count=1>
c6
<_RLock owner=None count=0>
c7
p1
p2
p5
('num:', 2, 'producer')
<_RLock owner='producer' count=1>
p6
<_RLock owner=None count=0>
p7
p1
p2
p5
('num:', 3, 'producer')
<_RLock owner='producer' count=1>
p6
<_RLock owner=None count=0>
p7
c1
c2
c5
('num:', 2, 'consumer')
<_RLock owner='consumer' count=1>
c6
<_RLock owner=None count=0>
c7
p1
p2
p5
('num:', 3, 'producer')
<_RLock owner='producer' count=1>
p6
<_RLock owner=None count=0>
p7
p1
p2
p3
c1
c2
c5
('num:', 2, 'consumer')
<_RLock owner='consumer' count=1>
c6
<_RLock owner=None count=0><_RLock owner='producer' count=1> c7p4 p5
('num:', 3, 'producer')
<_RLock owner='producer' count=1>
p6
<_RLock owner=None count=0>
p7
p1
p2
p3
c1
c2
c5
('num:', 2, 'consumer')
<_RLock owner='consumer' count=1>
c6
<_RLock owner=None count=0><_RLock owner='producer' count=1> c7p4 p5
('num:', 3, 'producer')
<_RLock owner='producer' count=1>
p6
<_RLock owner=None count=0>
p7
p1
p2
p3
c1
c2
c5
('num:', 2, 'consumer')
<_RLock owner='consumer' count=1>
c6
<_RLock owner='producer' count=1><_RLock owner=None count=1> p4c7 p5
('num:', 3, 'producer')
<_RLock owner='producer' count=1>
p6
<_RLock owner=None count=0>
p7
p1
p2
p3
c1
c2
c5
('num:', 2, 'consumer')
<_RLock owner='consumer' count=1>
c6
<_RLock owner=None count=0><_RLock owner='producer' count=1> c7p4 p5
('num:', 3, 'producer')
<_RLock owner='producer' count=1>
p6
<_RLock owner=None count=0>
p7
p1
p2
p3
c1
c2
c5
('num:', 2, 'consumer')
<_RLock owner='consumer' count=1>
c6
<_RLock owner=None count=0><_RLock owner='producer' count=1> c7p4 p5
('num:', 3, 'producer')
<_RLock owner='producer' count=1>
p6
<_RLock owner=None count=0>
p7
p1
p2
p3
c1
c2
c5
('num:', 2, 'consumer')
<_RLock owner='consumer' count=1>
c6
<_RLock owner=None count=0>
c7<_RLock owner='producer' count=1> p4
p5
('num:', 3, 'producer')
<_RLock owner='producer' count=1>
p6
<_RLock owner=None count=0>
p7
p1
p2
p3
c1
c2
c5
('num:', 2, 'consumer')
<_RLock owner='consumer' count=1>
c6
<_RLock owner=None count=0><_RLock owner='producer' count=1> c7p4 p5
('num:', 3, 'producer')
<_RLock owner='producer' count=1>
p6
<_RLock owner=None count=0>
p7 Process finished with exit code -1

3 输出解读:

4 相关资料

java中的notify和notifyAll有什么区别?

先说两个概念:锁池和等待池

  • 锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池中。
  • 等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁后,进入到了该对象的等待池中

Reference:java中的锁池和等待池

链接:https://www.zhihu.com/question/37601861/answer/145545371

然后再来说notify和notifyAll的区别

  • 如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁
  • 当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争
  • 优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。

Reference:线程间协作:wait、notify、notifyAll

综上,所谓唤醒线程,另一种解释可以说是将线程由等待池移动到锁池,notifyAll调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争。而notify只会唤醒一个线程。

有了这些理论基础,后面的notify可能会导致死锁,而notifyAll则不会的例子也就好解释了

个人理解:

[b0034] python 归纳 (十九)_线程同步_条件变量的更多相关文章

  1. Linux线程同步:条件变量

    条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其它 ...

  2. 线程同步,条件变量pthread_cond_wait

    与互斥锁不同,条件变量是用来等待而不是用来上锁的.条件变量用来自动阻塞一个线程,直到某特殊情况发生为止.条件变量使我们可以睡眠等待某种条件出现.条件变量是利用线程间共享的全局变量进行同步的一种机制,主 ...

  3. 四十二、Linux 线程——线程同步之条件变量之线程状态转换

    42.1 线程状态转换 42.1.1 状态转换图 42.1.2 一个线程计算,多个线程获取的案例 #include <stdio.h> #include <stdlib.h> ...

  4. UNIX环境高级编程——线程同步之条件变量以及属性

    条件变量变量也是出自POSIX线程标准,另一种线程同步机制.主要用来等待某个条件的发生.可以用来同步同一进程中的各个线程.当然如果一个条件变量存放在多个进程共享的某个内存区中,那么还可以通过条件变量来 ...

  5. linux线程同步(2)-条件变量

    一.概述                                                    上一篇,介绍了互斥量.条件变量与互斥量不同,互斥量是防止多线程同时访问共享的互斥变量来保 ...

  6. 四十一、Linux 线程——线程同步之条件变量

    41.1 概念 41.1.1 条件变量的介绍 互斥锁的缺点是它只有两种状态:锁定和非锁定 条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足 条件变量内部是一个等待队列,放置等待 ...

  7. [b0031] python 归纳 (十六)_线程同步_锁

    # -*- coding: utf-8 -*- """ 学习 多线程同步 使用锁 threading.Lock() 逻辑: 2 个线程,操作同一个整型变量,一个加法,另外 ...

  8. [b0032] python 归纳 (十七)_线程同步_信号量Semaphore

    代码: # -*- coding: utf-8 -*- """ 多线程并发同步 ,使用信号量threading.Semaphore 逻辑: 多个线程,对同一个共享变量 , ...

  9. Python并行编程(六):线程同步之条件

    1.基本概念 条件指的是应用程序状态的改变.其中某些线程在等待某一条件发生,其 他线程会在该条件发生的时候进行通知,一旦条件发生,线程会拿到共享资源的唯一权限. 2.示例代码 from threadi ...

随机推荐

  1. JS基础语法---Date对象中常见的方法

    创建实例对象 var dt = new Date(); //当前的时间---当前的服务器 console.log(dt); var dt = new Date("2017-08-12&quo ...

  2. jQuery基础之表单验证

    在使用jquery-validate.js插件时可以做一些初始化配置在初始化jquery-validate.js对象的时候,将外部的一些配置和该插件内部的一些默认配置合并在一起,如果有相同的配置,前者 ...

  3. iOS----------iPhone导出手机所有短信

    第一步:手机连接到itunes  选择本电脑备份   备份的时候不要加密  然后立即备份 第二步:前往文件夹,找到itunes的备份路径~/Library/Application Support/Mo ...

  4. Android 上下文菜单 PopupMenu

    @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); s ...

  5. ABP入门教程14 - 更新多语言

    点这里进入ABP入门教程目录 设置语种 新增语种 数据库操作 打开多语言表AbpLanguages,添加一条记录. 程序操作 在基础设施层(即JD.CRS.EntityFrameworkCore)的\ ...

  6. Consul作为配置中心,配置Asp.Net Core应用程序

    前言 最近项目逐步转向基于.Net Core,目前dotnet core 虽然已出3.0了但还没有特别成熟的框架,要实现微服务,必须要解决配置中心的问题 .不管是不是微服务,节点多了配置文件一个个更改 ...

  7. JUC-0-JUC简介

    Java JUC  简介   在 Java 5.0 提供了 java.util.concurrent (简称 JUC )包,在此包中增加了在并发编程中很常用 的实用工具类,用于定义类似于线程的自定义子 ...

  8. 201871010118-唐敬博《面向对象程序设计(java)》第一周学习总结

    博文正文开头格式:(3分) 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/p/11435127.html 这个作业的要求在哪里 https:/ ...

  9. 201871010102-常龙龙《面向对象程序设计(java)》第十五周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...

  10. mysql深入学习(一)

    Mysql高级学习 一.Mysql简介 1.概述 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司. MySQL是一种关联数据库管理系统,将数据保存在不同 ...