并发编程之多进程

  python中如果想要充分的利用多核CPU的资源,大部分情况需要使用多进程,python提供了multiprocessing

  multiprocessing模块用来开启子进程,并在子进程中执行定制的任务

#方式一
from multiprocessing import Process
import time def task(name):
print('%s is running'%name)
time.sleep(3)
print('%s is done'%name) if __name__ == '__main__':
p=Process(target=task,args=('alex',))
p.start()
print('主') #方式二
from multiprocessing import Process
import time class MyProcess(Process):
def __init__(self,name):
super(MyProcess,self).__init__()
self.name=name def run(self):
print('%s is running'%self.name)
time.sleep(3)
print('%s is done'%self.name) if __name__ == '__main__':
p=MyProcess('进程1')
p.start()
print('主')

  进程之间的内存空间是隔离的

from multiprocessing import Process

n = 100
def task():
global n
n = 0 if __name__ == '__main__':
p = Process(target=task)
p.start()
p.join()
print(p.is_alive()) #查看进程是否完毕
print('主', n) #进程之间的内存是互相隔离的

  Process对象的join()方法:主进程等待子进程结束

from multiprocessing import Process
import time
import os def task(n):
print('%s is running' % os.getpid())
time.sleep(n)
print('%s is done' % os.getpid()) if __name__ == '__main__':
start_time=time.time()
p1 = Process(target=task, args=(1,))
p2 = Process(target=task, args=(2,))
p3 = Process(target=task, args=(3,))
p_l = [p1, p2, p3]
# p1.start()
# p2.start()
# p3.start()
for p in p_l:
p.start() # p1.join()
# p2.join()
# p3.join()
for p in p_l:
p.join() stop_time=time.time()
print('主',stop_time-start_time)

join()方法

  Process对象的其他方法或属性

from multiprocessing import Process
import time
import os def task(n):
print('pid:%s ppid:%s' % (os.getpid(), os.getppid()))
time.sleep(n) if __name__ == '__main__':
p = Process(target=task,args=(15,),name='进程1')
p.start()
p.terminate() #终止进程
time.sleep(1)
print(p.is_alive()) #查看进程是否完毕
print('主...pid:%s ppid:%s' % (os.getpid(), os.getppid())) #主进程的ppid即为pycharm
print(p.pid) #查看进程pid
print(p.name) #查看进程名

  僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中,这种进程称之为僵尸进程

  孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将称为孤儿进程,孤儿进程将被init进程所收养,并由init进程对它们完成状态收集工作

  守护进程:守护进程会在主进程代码执行结束后就终止;守护进程内无法再开启子进程,否则抛出异常;进程之间是互相独立的,主进程代码运行结束,守护进程随即终止

from multiprocessing import Process
import time def task(name):
print('%s is running' % name)
time.sleep(3)
print('%s is done' % name) if __name__ == '__main__':
p = Process(target=task,args=('lary',))
p.daemon = True #将子进程设置为守护进程
p.start() print('主')

  进程同步:进程之间如果共享同一套资源会带来竞争,通过加锁处理来控制资源竞争,加锁可以保证多个进程修改同一块数据时,同一时间只有一个任务可以修改,即串行的修改,牺牲了速度却保证了数据安全

#互斥锁
from multiprocessing import Process,Lock
import json
import time
import random
import os def search():
time.sleep(random.randint(1,3))
dic=json.load(open('db.txt','r',encoding='utf-8'))
print('%s 查看剩余票数%s'%(os.getpid(),dic["count"])) def get():
dic=json.load(open('db.txt','r',encoding='utf-8'))
if dic["count"] > 0:
dic["count"]-=1
time.sleep(random.randint(1,3))
json.dump(dic,open('db.txt','w',encoding='utf-8'))
print('%s 购票成功'%os.getpid()) def task(mutex):
search()
mutex.acquire() #加锁
get()
mutex.release() #解锁 if __name__ == '__main__':
mutex=Lock() #创建实例对象
for i in range(10):
p=Process(target=task,args=(mutex,))
p.start()

互斥锁

  队列:进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种模式:队列和管道

#队列
from multiprocessing import Queue q=Queue(3)
q.put('first')
q.put(2)
q.put({"count":3})
#q.put('fourth')
#q.put('fourth',block=False)
#q.put('fourth',block=True,timeout=3) print(q.get())
print(q.get())
print(q.get())
#print(q.get())
#print(q.get(block=False))
print(q.get(block=True,timeout=3))

  生产者消费者模型

  生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力

#生产者消费者模型
from multiprocessing import Process,JoinableQueue
import time
import random def producer(name,food,q):
for i in range(2):
res='%s%s'%(food,i)
time.sleep(random.randint(1,3))
q.put(res)
print('厨师[%s]生产了<%s>'%(name,res)) def consumer(name,q):
while True:
res=q.get()
#if res is None:break
time.sleep(random.randint(1,3))
print('吃货[%s]吃了<%s>'%(name,res))
q.task_done() if __name__ == '__main__':
q=JoinableQueue()
p1 = Process(target=producer,args=('egon1','peach',q))
p2 = Process(target=producer, args=('egon2', 'peach', q)) c1 = Process(target=consumer,args=('lary1',q))
c2 = Process(target=consumer, args=('lary2', q)) c1.daemon=True
c2.daemon=True p1.start()
p2.start() c1.start()
c2.start() p1.join()
p2.join() q.join()
print('主')

基于队列实现生产者消费者模型

并发编程之多线程

  开启线程的两种方式

from threading import Thread
import time
import random #开启线程方式一
def eat(name):
print('%s is eating'%name)
time.sleep(random.randint(1,3))
print('%s eating end'%name) if __name__ == '__main__':
t1=Thread(target=eat,args=('lary',))
t1.start()
print('主') #开启线程方式二
class MyThread(Thread):
def __init__(self,name):
super().__init__()
self.name=name def run(self):
print('%s is eating' %self.name)
time.sleep(random.randint(1,3))
print('%s eating end'%self.name) if __name__ == '__main__':
t1=MyThread('lary')
t1.start()
print('主')
from threading import Thread,current_thread
from socket import * def communicate(conn):
print('子线程:%s'%current_thread().getName())
while True:
try:
data=conn.recv(1024)
if not data:break
conn.send(data.upper())
except ConnectionResetError:
break
conn.close() def server(ip,port):
print('主线程:%s'%current_thread().getName())
server=socket(AF_INET,SOCK_STREAM)
server.bind((ip,port))
server.listen(5) while True:
conn,addr=server.accept()
print(addr)
t=Thread(target=communicate,args=(conn,))
t.start() server.close() if __name__ == '__main__':
server('127.0.0.1',8081)

多线程并发的服务端

from socket import *

client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8081)) while True:
msg=input('>>:').strip()
if not msg:continue
client.send(msg.encode('utf-8'))
data=client.recv(1024)
print(data.decode('utf-8')) client.close()

客户端

  线程相关的其他方法

#Thread实例对象的方法
# isAlive(): 返回线程是否活动的。
# getName(): 返回线程名。
# setName(): 设置线程名。 #threading模块提供的一些方法:
# threading.currentThread(): 返回当前的线程变量。
# threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
# threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

  守护线程

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())

第十三章 Python并发编程的更多相关文章

  1. 第 12 章 python并发编程之协程

    一.引子 主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只用一个)情况下实现并发,并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去执行其他的任务(切换由操作 ...

  2. python并发编程&多线程(二)

    前导理论知识见:python并发编程&多线程(一) 一 threading模块介绍 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性 官网链 ...

  3. Python并发编程内容回顾

    Python并发编程内容回顾 并发编程小结 目录 • 一.到底什么是线程?什么是进程? • 二.Python多线程情况下: • 三.Python多进程的情况下: • 四.为什么有这把GIL锁? • 五 ...

  4. Python并发编程理论篇

    Python并发编程理论篇 前言 其实关于Python的并发编程是比较难写的一章,因为涉及到的知识很复杂并且理论偏多,所以在这里我尽量的用一些非常简明的语言来尽可能的将它描述清楚,在学习之前首先要记住 ...

  5. Python并发编程__多进程

    Python并发编程_多进程 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大 ...

  6. Python并发编程的几篇文章

    Python几种并发实现方案的性能比较 http://www.elias.cn/Python/PyConcurrency?from=Develop.PyConcurrency python并发编程 h ...

  7. Python并发编程之深入理解yield from语法(八)

    大家好,并发编程 进入第八篇. 直到上一篇,我们终于迎来了Python并发编程中,最高级.最重要.当然也是最难的知识点--协程. 当你看到这一篇的时候,请确保你对生成器的知识,有一定的了解.当然不了解 ...

  8. 自学Python之路-Python并发编程+数据库+前端

    自学Python之路-Python并发编程+数据库+前端 自学Python之路[第一回]:1.11.2 1.3

  9. Python并发编程二(多线程、协程、IO模型)

    1.python并发编程之多线程(理论) 1.1线程概念 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程(流水线的工作需要电源,电源就相当于 ...

随机推荐

  1. 在虚拟机安装Oracle,在本地电脑上运行sql develer出现ora-12514

    问题是解决了,先描述一下,本人用的虚拟机系统是server 2003 1.打开虚拟机,然后不管了 2.打开本地的sql developer,登录,出现了一个小白框:ora-12514:listener ...

  2. js进度条插件pace.js

    主要用到themes文件夹和pace.js文件

  3. 【BZOJ3451】Tyvj1953 Normal - 点分治+FFT

    题目来源:NOI2019模拟测试赛(七) 非原题面,题意有略微区别 题意: 吐槽: 心态崩了. 好不容易场上想出一题正解,写了三个小时结果写了个假的点分治,卡成$O(n^2)$ 我退役吧. 题解: 原 ...

  4. css实现三栏水平布局双飞翼与圣杯布局

    作为布局的入门级选手,网上也查看了很多信息和资源 双飞翼的html结构 <div class="container"> <div class="main ...

  5. JavaScript 原型 原型链

    一. 普通对象与函数对象 JavaScript 中,万物皆对象!但对象也是有区别的.分为普通对象和函数对象,Object .Function 是 JS 自带的函数对象.下面举例说明 var o1 = ...

  6. Project Euler 44 Sub-string divisibility( 二分 )

    题意:五边形数由公式Pn=n(3n−1)/2生成,在所有和差均为五边形数的五边形数对Pj和Pk中,找出使D = |Pk − Pj|最小的一对:此时D的值是多少? 思路:二分找和差 /********* ...

  7. [SDOI2016]生成魔咒(后缀自动机)

    看一眼题.本质不同的字串数. 嘴角微微上扬. 每一次加一个数输出一个答案. 笑容渐渐消失. 等等,\(SAM\)好像也可以求本质不同的字串. 设当前字符串用\(x\)表示,每次插入完成后\(ans\) ...

  8. PHP开发过程中数组汇总 [ 持续更新系列 ]

    开发过程中经常会使用到数组函数,故特地总结出来,自己熟悉,同时供大家参考!(实例部分会抽空尽快完成) 一.目录 array_merge(); 合并数组 array_keys(); array_filt ...

  9. 《你又怎么了我错了行了吧》【Alpha】Scrum meeting 3

    第三天 日期:2019/6/16 前言: 第3次会议在女生宿舍召开 讨论了项目功能改进问题,继续代码完善和安排 1.1 今日完成任务情况以及明天任务安排 姓名 当前阶段任务 下一阶段任务 刘 佳 对已 ...

  10. C#强化系列:HttpModule,HttpHandler,HttpHandlerFactory简单使用

    这三个对象我们在开发Asp.net程序时经常会用到,似乎很熟悉,但有时候又不太确定.本文通过一个简单的例子来直观的比较一下这三个对象的使用.HttpModule:Http模块,可以在页面处理前后.应用 ...