4月26日 python学习总结 JoinableQueue、线程、三种锁
一、进程队列补充-创建进程队列的另一个类JoinableQueue
JoinableQueue同样通过multiprocessing使用。
创建队列的另外一个类:
JoinableQueue([maxsize]):这就像是一个Queue对象,但队列允许项目的使用者通知生成者项目已经被成功处理。通知进程是使用共享的信号和条件变量来实现的。
参数介绍:
1 import time
2 import random
3 from multiprocessing import Process,JoinableQueue
4
5 def consumer(name,q):
6 while True:
7 res=q.get()
8 if res is None:break
9 time.sleep(random.randint(1,3))
10 print('\033[46m消费者===》%s 吃了 %s\033[0m' %(name,res))
11 q.task_done()
12
13 def producer(name,q,food):
14 for i in range(5):
15 time.sleep(random.randint(1,2))
16 res='%s%s' %(food,i)
17 q.put(res)
18 print('\033[45m生产者者===》%s 生产了 %s\033[0m' %(name,res))
19
20
21
22 if __name__ == '__main__':
23 #1、共享的盆
24 q=JoinableQueue()
25
26
27 #2、生产者们
28 p1=Process(target=producer,args=('egon',q,'包子'))
29 p2=Process(target=producer,args=('刘',q,'泔水'))
30 p3=Process(target=producer,args=('杨',q,'米饭'))
31
32 #3、消费者们
33 c1=Process(target=consumer,args=('alex',q))
34 c2=Process(target=consumer,args=('梁',q))
35 c1.daemon=True
36 c2.daemon=True
37
38 p1.start()
39 p2.start()
40 p3.start()
41 c1.start()
42 c2.start()
43
44
45 # 确定生产者确确实实已经生产完毕
46 p1.join()
47 p2.join()
48 p3.join()
49 # 在生产者生产完毕后,拿到队列中元素的总个数,然后直到元素总数变为0,q.join()这一行代码才算运行完毕
50 q.join()
51 #q.join()一旦结束就意味着队列确实被取空,消费者已经确确实实把数据都取干净了
52 print('主进程结束')
生产者消费者模型例子
二、线程
1、什么是线程
线程指的是一条流水线的工作过程
进程根本就不是一个执行单位,进程其实是一个资源单位
一个进程内自带一个线程,线程才是执行单位
2、进程VS线程
- 同一进程内的线程们共享该进程内资源,不同进程内的线程资源肯定是隔离的
- 创建线程的开销比创建进程要小的多
- 一个进程的所有线程的pid都是一样的
- 线程之间的地位相同,没有主次之分,但是主线程又代表着主进程
3、创建线程的两种方式
#方式一
from threading import Thread
import time
def sayhi(name):
print('%s say hello' %name) if __name__ == '__main__':
t=Thread(target=sayhi,args=('egon',))
t.start()
print('主线程')
#方式二
from threading import Thread
import time
class Sayhi(Thread):
def __init__(self,name):
super().__init__()
self.name=name
def run(self):
print('%s say hello' % self.name) if __name__ == '__main__':
t = Sayhi('egon')
t.start()
print('主线程')
线程执行的结果:

与进程不同,是因为线程启动的代价很小,启动速度远大于进程,所以,子线程先打印,主线程才打印
from threading import Thread,current_thread,active_count,enumerate
import time,os def task():
print('%s is running' %current_thread().name)
time.sleep(3) if __name__ == '__main__':
t1=Thread(target=task,name='第一个线程')
t2=Thread(target=task,)
t3=Thread(target=task,)
t1.start()
t2.start()
t3.start() # print(t1.is_alive()) #查看线程是否存活
print(active_count()) #查看活跃的线程数,包括主线程
print(enumerate()) #获取当前每个活跃的线程对象
print('主线程',current_thread().name) #获取当前线程名
Thread实例对象的方法
# isAlive(): 返回线程是否活动的。
# getName(): 返回线程名。
# setName(): 设置线程名。 threading模块提供的一些方法:
# threading.currentThread(): 返回当前的线程变量。
# threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
# threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
5、守护线程
t.daemon=true
# 设为守护线程,守护线程要在线程开始执行之前设置,否则报错
无论是进程还是线程,都遵循:守护xxx会等待主xxx运行完毕后被销毁
需要强调的是:运行完毕并非终止运行
1 .对主进程来说,运行完毕指的是主进程代码运行完毕
2. 对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕
详细解释:
- 主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束
- 主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,进程整体的资源都将被回收,而进程必须保证非守护线程都运行完毕后才能结束。
from threading import Thread
import time
def sayhi(name):
time.sleep(2)
print('%s say hello' %name) if __name__ == '__main__':
t=Thread(target=sayhi,args=('egon',))
t.setDaemon(True) #必须在t.start()之前设置
t.start() print('主线程')
print(t.is_alive())
'''
主线程
True
'''
三、死锁现象;互斥锁、递归锁、信号量
死锁现象
1 from threading import Thread,Lock,RLock
2 import time
3
4 mutexA=Lock()
5 mutexB=Lock()
6
7 class MyThread(Thread):
8 def run(self):
9 self.f1()
10 self.f2()
11
12 def f1(self):
13 mutexA.acquire()
14 print('%s 拿到了A锁' %self.name)
15
16 mutexB.acquire()
17 print('%s 拿到了B锁' %self.name)
18 mutexB.release()
19
20 mutexA.release()
21
22 def f2(self):
23 mutexB.acquire()
24 print('%s 拿到了B锁' %self.name)
25 time.sleep(0.1)
26
27 mutexA.acquire()
28 print('%s 拿到了A锁' %self.name)
29 mutexA.release()
30
31 mutexB.release()
32
33
34 if __name__ == '__main__':
35 for i in range(10):
36 t=MyThread()
37 t.start()
38
39 print('主')
死锁
解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。
这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁:
mutexA=mutexB=threading.RLock() #一个线程拿到锁,counter加1,该线程内又碰到加锁的情况,则counter继续加1,这期间所有其他线程都只能等待,等待该线程释放所有锁,即counter递减到0为止
信号量
同进程的一样
Semaphore管理一个内置的计数器,
每当调用acquire()时内置计数器-1;
调用release() 时内置计数器+1;
计数器不能小于0;当计数器为0时,acquire()将阻塞线程直到其他线程调用release()。
实例:(同时只有5个线程可以获得semaphore,即可以限制最大连接数为5):
# from multiprocessing import Semaphore from threading import Thread,Semaphore,current_thread
import time,random sm=Semaphore(5) def go_wc():
sm.acquire()
print('%s 上厕所ing' %current_thread().getName())
time.sleep(random.randint(1,3))
sm.release() if __name__ == '__main__':
for i in range(23):
t=Thread(target=go_wc)
t.start()
4月26日 python学习总结 JoinableQueue、线程、三种锁的更多相关文章
- 6月6日 python学习总结 jQuery (三)
1. 常用事件 1. hover #鼠标悬停监听 2. keydown和keyup #键盘按键 按下/抬起 3. change #监听值的改变 全部输入完失去焦点后 4. focus和blur # 获 ...
- 4月2日 python学习总结
昨天内容回顾: 1.迭代器 可迭代对象: 只要内置有__iter__方法的都是可迭代的对象 既有__iter__,又有__next__方法 调用__iter__方法==>得到内置的迭代器对象 调 ...
- 4月8日 python学习总结 模块与包
一.包 #官网解释 Packages are a way of structuring Python's module namespace by using "dotted module n ...
- 5月14日 python学习总结 视图、触发器、事务、存储过程、函数、流程控制、索引
一.视图 1.什么是视图 视图就是通过查询得到一张虚拟表,然后保存下来,下次用的直接使用即可 2.为什么要用视图 如果要频繁使用一张虚拟表,可以不用重复查询 3.如何用视图 create view t ...
- 4月12日 python学习总结 继承和派生
一.继承 什么是继承: 继承是一种新建类的方式,在python中支持一个子类继承多个父类 新建类称为子类或派生类 父类可以称之为基类或者超类 子类会遗传父类的属性 2. 为什么继承 ...
- 4月11日 python学习总结 对象与类
1.类的定义 #类的定义 class 类名: 属性='xxx' def __init__(self): self.name='enon' self.age=18 def other_func: pas ...
- 4月3日 python学习总结
1. 列表生成器 l=['egg%s' %i for i in range(100) if i>20 ] print(l) 若将 [ ] 换成 ( ),则为生成器表达式,结果是一个迭代器 #求文 ...
- 4月17日 python学习总结 反射、object内置方法、元类
一.反射 下述四个函数是专门用来操作类与对象属性的,如何操作? 通过字符串来操作类与对象的属性,这种操作称为反射 class People: country="China" def ...
- 4月4日 python学习总结 os pickle logging
1.序列化和反序列化 我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling. 反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickl ...
随机推荐
- c++ struct enum union加typedef与不加typedef
struct/enum/union加typedef与不加typedef 匿名结构体 struct { int a; int b; } v; // 这里表示定义了一个结构体的变量v,且结构体类型没有名字 ...
- SpringBoot 自定义参数类型转换convert
创建一个配置类.使用 @bean注入到容器中 @Bean public WebMvcConfigurer webMvcConfigurer(){ /** * 实现自定义的addConverter */ ...
- mongodb4.x 集群搭建
下载包 官网选择合适的操作系统版本下载tgz包 https://www.mongodb.com/download-center/community 部署结构 集群结构 典型的三分片Mongo集群如下图 ...
- 如何基于gRPC沟通微服务框架
本文我们来讲解一下如何使用 gRPC构建微服务,gRPC是一个开源框架,可用于构建可扩展且高性能的微服务并创建服务之间的通信. 背景 随着企业越来越多地转向微服务,对构建这些微服务的低延迟和可扩展框架 ...
- python-利用xlrd模块读取excel数据,将excel数据转换成字典格式
前言 excel测试案例数据 转换成这种格式 实现代码 import os import xlrd excel_path = '..\data\\test_case.xlsx' data_path = ...
- k8s搭建监控:安装metrics server和dashboard
安装metrics server 参考:https://github.com/kubernetes-sigs/metrics-server kubectl create -f component ...
- k8s被删除的pod一直Terminating状态
微服务项目,部分服务无法delete,一直处于Terminating状态 kubectl get po -n gift 强制删除product:kubectl delete -n gift po/pr ...
- Smartbi报表制作:25个主流车企月热销表
今天给大家分享的是 25个主流车企月热销表 这张移动端报表的制作过程. 制作工具:Smartbi云报表 Smartbi云报表是一款基于Office Excel的SAASBI工具,支持在Excel端结合 ...
- 二分查找法&大O表示法
二分查找法的输入是一个有序的元素列表,如果要查找的元素包含在列表中,二分查找返回其位置,否则返回null Python代码(来源于<算法图解>一书): def binary_search( ...
- Spring源码之六-onRefresh()方法
Spring源码之六-onRefresh()方法 大家好,我是程序员田同学. 今天带大家解读Spirng源码之六的onRefresh()方法,这是refresh()的其中的一个方法,看似是一个空方法, ...