11-僵尸进程与孤儿进程
现象:运行程序会产生父进程,在父进程中开子进程,这两个进程公用一个打印终端,运行的时候就只运行父进程,父进程虽然自己结束了,但是要等子进程结束完才会结束。
父进程可以开多个子进程,进程间是互相独立的,需要让父进程提供任何时刻都可以查看子进程状态的功能
僵尸进程是unix或linux系统提供的一种数据结构,即使子进程已经结束了,那么父进程也可以查看子进程的状态,父进程在自己结束的时候会发起系统命令wait,结束所有的僵尸子进程
1.所有的子进程都是要经历僵尸进程的状态的
2.僵尸进程是有害的,因为进程的pid还在占用,僵尸进程多了,会占用多个pid,如果父进程一直不结束,僵尸进程会一直不结束,那么新的子进程就会难开启
孤儿进程:子进程没结束,但是父进程结束了,那么子进程就会被init的进程接管,init是所有进程的父进程,孤儿进程是无害的

12-Process对象的其他属性或方法
如果主进程需要等待子进程结束以后才能运行,就需要join方法
只有主进程会在等,但是子进程不会等,会一直运行子进程
from multiprocessing import Process
import time
import os
def task():
print('%s is running.Parent is is %s' % (os.getpid(),os.getppid()))
time.sleep(4)
print('%s is done.Parent is is %s' % (os.getpid(),os.getppid()))
# windows操作系统一定要在main下执行Process
if __name__ == '__main__':
p1 = Process(target=task) #实例化一个对象
p2 = Process(target=task) #实例化一个对象
p1.start() #仅仅是给操作系统发送了一个信号
p2.start()
p1.join()
p2.join()
print('主进程结束',os.getpid(),os.getppid())
输出结果
 
start()给操作系统发送了一个信号,是由操作系统去调度是否启动线程,执行顺序是无法确定的!
from multiprocessing import Process
import time
import os
def task(name):
print('%s is running' % name)
time.sleep(4)
 
# windows操作系统一定要在main下执行Process
if __name__ == '__main__':
p1 = Process(target=task, args=('子进程1',)) #实例化一个对象
p2 = Process(target=task, args=('子进程2',)) #实例化一个对象
p3 = Process(target=task, args=('子进程3',))
p1.start() #仅仅是给操作系统发送了一个信号,是由操作系统去调度是否启动线程,执行顺序是无法确定的!
p2.start()
p3.start()
 
print('主进程结束',os.getpid(),os.getppid())
print(p1.pid)
start+join方法的执行方式最后的执行时间是以子进程的最长执行时间为准,并不是串行的
from multiprocessing import Process
import time
import os
def task(name, n):
    print('%s is running' % name)
    time.sleep(n)
 
# windows操作系统一定要在main下执行Process
if __name__ == '__main__':
    start = time.time()
    p1 = Process(target=task, args=('子进程1',1)) #实例化一个对象
    p2 = Process(target=task, args=('子进程2',3)) #实例化一个对象
    p3 = Process(target=task, args=('子进程3',5))
    p1.start() #仅仅是给操作系统发送了一个信号,是由操作系统去调度是否启动线程,执行顺序是无法确定的!
    p2.start()
    p3.start()
    p1.join()
    p2.join()
    p3.join()
    print('主进程结束',(time.time()-start))
串行的执行方法
from multiprocessing import Process
import time
import os
def task(name, n):
    print('%s is running' % name)
    time.sleep(n)
 
# windows操作系统一定要在main下执行Process
if __name__ == '__main__':
    start = time.time()
    p1 = Process(target=task, args=('子进程1',1)) #实例化一个对象
    p2 = Process(target=task, args=('子进程2',3)) #实例化一个对象
    p3 = Process(target=task, args=('子进程3',5))
    p1.start() #仅仅是给操作系统发送了一个信号,是由操作系统去调度是否启动线程,执行顺序是无法确定的!
    p1.join()
    p2.start()
    p2.join()
    p3.start()
    p3.join()
    print('主进程结束',(time.time()-start))
is_alive()->查看进程是否在运行
terminate()->交给操作系统,对这个进程进行回收(不是立刻回收,操作系统需要一点时间对内存进行释放)
name->进程的名称

13-练习题讲解

四 练习题

1、思考开启进程的方式一和方式二各开启了几个进程?
不算pycharm本身的进程
方式一:两个进程:1.py文件父进程;2.程序生成子进程
方式二:两个进程:2.py文件父进程;2.程序生成子进程
2、进程之间的内存空间是共享的还是隔离的?下述代码的执行结果是什么?
from multiprocessing import Process
 
n=100 #在windows系统中应该把全局变量定义在if __name__ == '__main__'之上就可以了
 
def work():
global n
n=0
print('子进程内: ',n)
 
 
if __name__ == '__main__':
p=Process(target=work)
p.start()
print('主进程内: ',n)
进程之间的内存空间是隔离的,执行结果
3、基于多进程实现并发的套接字通信?
服务端
import socket
from multiprocessing import Process
def talk(conn):
    while True:
        try:
            data = conn.recv(1024)
            if not data:break
            conn.send(data.upper())
        except ConnectionError:
            break
    conn.close()
 
 
 
def server():
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server.bind(('127.0.0.1', 8080))
    server.listen(5)
    while True:
        conn, addr = server.accept()
        p = Process(target=talk, args=(conn,))
        p.start()
    server.close()
 
if __name__ == '__main__':
    server()
 
 
客户端
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 8080))
while True:
msg = input('>>>>').strip()
if not msg:continue
client.send(msg.encode('gbk'))
data = client.recv(1024)
print(data.decode('gbk'))
4、思考每来一个客户端,服务端就开启一个新的进程来服务它,这种实现方式有无问题?
来一个客户端就要对服务端的机器启动一个进程,就要占内存空间,很多个客户端就会让服务端的内存爆炸!
 

三 练习题

1、改写下列程序,分别别实现下述打印效果
from multiprocessing import Process
import time
import random
 
def task(n):
time.sleep(random.randint(1,3))
print('-------->%s' %n)
 
if __name__ == '__main__':
p1=Process(target=task,args=(1,))
p2=Process(target=task,args=(2,))
p3=Process(target=task,args=(3,))
 
p1.start()
p2.start()
p3.start()
 
print('-------->4')
效果一:保证最先输出-------->4
-------->4
-------->1
-------->3
-------->2
 
from multiprocessing import Process
import time
import random
 
def task(n):
    time.sleep(random.randint(1,3))
    print('-------->%s' % n)
 
if __name__ == '__main__':
    p1=Process(target=task,args=(1,))
    p2=Process(target=task,args=(2,))
    p3=Process(target=task,args=(3,))
 
    p1.start()
    p2.start()
    p3.start()
    print('-------->4')
    p1.join()
    p2.join()
    p3.join()
效果二:保证最后输出-------->4
-------->2
-------->3
-------->1
-------->4
 
from multiprocessing import Process
import time
import random
 
def task(n):
    time.sleep(random.randint(1,3))
    print('-------->%s' % n)
 
if __name__ == '__main__':
    p1=Process(target=task,args=(1,))
    p2=Process(target=task,args=(2,))
    p3=Process(target=task,args=(3,))
 
    p1.start()
    p2.start()
    p3.start()
    p1.join()
    p2.join()
    p3.join()
    print('-------->4')
效果三:保证按顺序输出
-------->1
-------->2
-------->3
-------->4
 
from multiprocessing import Process
import time
import random
 
def task(n):
    time.sleep(random.randint(1,3))
    print('-------->%s' % n)
 
if __name__ == '__main__':
    p1=Process(target=task,args=(1,))
    p2=Process(target=task,args=(2,))
    p3=Process(target=task,args=(3,))
 
    p1.start()
    p1.join()
    p2.start()
    p2.join()
    p3.start()
    p3.join()
    print('-------->4')
2、判断上述三种效果,哪种属于并发,哪种属于串行?
效果一:并发
效果二:并发
效果三:串行
 

14-守护进程
主进程里设置子进程的目的是为了执行一个并发的任务
假设这个子进程的运行周期是伴随着主进程一起执行的,也就是主进程结束,不管子进程是不是执行完,都要结束,那么这就是守护进程
守护进程的特点:
1.守护进程在主进程代码结束后就终止
2.守护进程内无法再开启子进程,否则就会抛出异常
如果有两个任务需要并发执行,那么开一个主进程和一个子进程分别执行就可以,如果子进程的任务在主进程任务结束后就不需要存在了,那么该子进程在开启前就需要设置为守护进程,主进程代码运行结束,守护进程就会终止
from multiprocessing import Process
import time
 
 
def task(name):
    print('%s in running' % name)
    time.sleep(2)
 
if __name__ == '__main__':
    p = Process(target=task, args=(('子进程1',)))
    # 守护进程的设置一定是要在子进程开始之前设置守护进程
    p.daemon = True
    p.start()
    
    print('主进程结束')
 
# 练习题
from multiprocessing import Process
import time
 
def foo():
    print('123')
    time.sleep(1)
    print('end123')
 
 
def bar():
    print('456')
    time.sleep(3)
    print('end456')
 
 
if __name__ == '__main__':
    p1 = Process(target=foo)
    p2 = Process(target=bar)
    p1.daemon = True
    p1.start()
    p2.start()
    time.sleep(0.5)
    print('主进程结束')
 
主进程已经结束了,守护进程也会跟着结束

15-互斥锁
进程与进程之间的数据是不共享的,但是多个进程可以访问同一个文件数据或同一个打印终端,共享带来的问题就是竞争,但是竞争带来的问题就是错乱
from multiprocessing import Process
import time
 
 
def task(name):
    print('%s 1' % name)
    time.sleep(1)
    print('%s 2' % name)
    time.sleep(1)
    print('%s 3' % name)
 
 
if __name__ == '__main__':
    for i in range(3):
        p = Process(target=task, args=('进程%s' % i,))
        p.start()

这样会造成混乱,无法判断哪一个进程在执行

互斥锁:把本来共享的文件数据或者共享的终端数据,让进程一个一个的运行,把并发变成串行了,就不会混乱
但是效率就降低了,所以互斥锁就是牺牲了效率来保证自己的进程执行顺序不会混乱
from multiprocessing import Process,Lock
import time
 
 
def task(name,mutex):
    # 为自己的子进程加锁
    mutex.acquire()
    print('%s 1' % name)
    time.sleep(1)
    print('%s 2' % name)
    time.sleep(1)
    print('%s 3' % name)
#     释放子进程的锁
    mutex.release()
 
if __name__ == '__main__':
    mutex = Lock()
    for i in range(3):
        p = Process(target=task, args=('进程%s' % i,mutex))
        p.start()

16-模拟抢票
一个进程就像是一个抢票的人,一个人把自己的请求提出给12306的网站,提取数据,修改数据就成功
要求启用多个进程修改同一个数据
# 抢票的环节
# 1.先去看网站的票数
# 2.假设票数如果为0就不能再买票了
import time
import json
from multiprocessing import Process, Lock
 
def search(name):
time.sleep(1) #模拟网络延迟
dic = json.load(open('db.txt', 'r', encoding='utf-8'))
print('<%s> 查看剩余的票数[%s]' % (name, dic['count']))
 
 
def get(name):
time.sleep(1)
dic = json.load(open('db.txt', 'r', encoding='utf-8'))
if dic['count'] > 0:
dic['count'] -= 1
time.sleep(3)
json.dump(dic, open('db.txt', 'w', encoding='utf-8'))
print('<%s>购票成功!' % name)
 
 
def task(name, mutex):
search(name)
mutex.acquire()
get(name)
mutex.release()
 
 
if __name__ == '__main__':
mutex = Lock()
for i in range(10):
p = Process(target=task, args=('路人%s' % i, mutex))
p.start()


17-互斥锁与join的区别
join确实能把并发变成串行,但是整个代码全部都是串行了,实际上是不合理的
但是互斥锁可以对代码进行分割,只是部分变成串行,这样更合理
# 抢票的环节
# 1.先去看网站的票数
# 2.假设票数如果为0就不能再买票了
import time
import json
from multiprocessing import Process, Lock
 
def search(name):
    time.sleep(1) #模拟网络延迟
    dic = json.load(open('db.txt', 'r', encoding='utf-8'))
    print('<%s> 查看剩余的票数[%s]' % (name, dic['count']))
 
 
def get(name):
    time.sleep(1)
    dic = json.load(open('db.txt', 'r', encoding='utf-8'))
    if dic['count'] > 0:
        dic['count'] -= 1
        time.sleep(3)
        json.dump(dic, open('db.txt', 'w', encoding='utf-8'))
        print('<%s>购票成功!' % name)
    else:
        print('<%s>购票失败!'%name)
 
def task(name, ):
    search(name)
    # mutex.acquire()
    get(name)
    # mutex.release()
 
 
if __name__ == '__main__':
    # mutex = Lock()
    for i in range(10):
        p = Process(target=task, args=('路人%s' % i, ))
        p.start()
        p.join()

18-队列的使用

19-生产者消费者模型

20-JoinableQueue的使用

21-什么是线程

22-开启线程的两种方式

23-进程与线程的区别

24-Thread对象的其他属性或方法

25-守护线程

26-互斥锁

27-GIL的基本概念

28-GIL与自定义互斥锁的区别

29-GIL与多线程

30-死锁与递归锁

31-信号量

32-Event事件

33-定时器

34-线程queue

35-多线程实现并发的套接字通信

36-进程池线程池

37-异步调用与回调机制

38-进程池线程池小练习

39-协程介绍

40-协程实现与总结

41-greenlet模块

42-gevent模块

43-gevent异步提交任务

44-基于gevent模块实现并发的套接字通信

45-IO模型介绍

46-阻塞IO模型

47-非阻塞IO模型

48-多路复用IO模型

49-异步IO模型

 
 
 

路飞学城Python-Day30的更多相关文章

  1. 路飞学城—Python爬虫实战密训班 第三章

    路飞学城—Python爬虫实战密训班 第三章 一.scrapy-redis插件实现简单分布式爬虫 scrapy-redis插件用于将scrapy和redis结合实现简单分布式爬虫: - 定义调度器 - ...

  2. 路飞学城—Python爬虫实战密训班 第二章

    路飞学城—Python爬虫实战密训班 第二章 一.Selenium基础 Selenium是一个第三方模块,可以完全模拟用户在浏览器上操作(相当于在浏览器上点点点). 1.安装 - pip instal ...

  3. 路飞学城Python爬虫课第一章笔记

    前言 原创文章,转载引用务必注明链接.水平有限,如有疏漏,欢迎指正. 之前看阮一峰的博客文章,介绍到路飞学城爬虫课程限免,看了眼内容还不错,就兴冲冲报了名,99块钱满足以下条件会返还并送书送视频. 缴 ...

  4. 路飞学城-Python开发集训-第3章

    学习心得: 通过这一章的作业,使我对正则表达式的使用直接提升了一个level,虽然作业完成的不怎么样,重复代码有点多,但是收获还是非常大的,有点找到写代码的感觉了,遗憾的是,这次作业交过,这次集训就结 ...

  5. 路飞学城-Python开发集训-第1章

    学习体会: 在参加这次集训之前我自己学过一段时间的Python,看过老男孩的免费视频,自我感觉还行,老师写的代码基本上都能看懂,但是实际呢?....今天是集训第一次交作业的时间,突然发现看似简单升级需 ...

  6. 路飞学城-Python开发集训-第4章

    学习心得: 学习笔记: 在python中一个py文件就是一个模块 模块好处: 1.提高可维护性 2.可重用 3.避免函数名和变量名冲突 模块分为三种: 1.内置标准模块(标准库),查看所有自带和第三方 ...

  7. 路飞学城-Python开发集训-第2章

    学习心得: 这章对编码的讲解超级赞,现在对于编码终于有一点认知了,但还没有大彻大悟,还需要更加细心的琢磨一下Alex博客和视频,以前真的是被编码折磨死了,因为编码的问题而浪费的时间很多很多,现在终于感 ...

  8. 路飞学城-Python开发-第二章

    ''' 数据结构: menu = { '北京':{ '海淀':{ '五道口':{ 'soho':{}, '网易':{}, 'google':{} }, '中关村':{ '爱奇艺':{}, '汽车之家' ...

  9. 路飞学城-Python开发-第三章

    # 数据结构: # goods = [ # {"name": "电脑", "price": 1999}, # {"name&quo ...

  10. 路飞学城-Python开发-第一章

    # 基础需求: # 让用户输入用户名密码 # 认证成功后显示欢迎信息 # 输错三次后退出程序 username = 'pandaboy' password = ' def Login(username ...

随机推荐

  1. struts中日期处理以及文件下载

    日期处理 对于jsp提交的基本数据类型和日期格式为yyyy-MM-dd的自动转换为相应的 对于其它的日期格式需要自定义转换器 局部类型转换器 1,写转换器类(继承StrutsTypeConverter ...

  2. 什么时候用created,什么时候用mounted

    created 在实例创建完成后被立即调用.在这一步,实例已完成以下的配置:数据观测 (data observer), 属性和方法的运算,watch/event 事件回调.然而,挂载阶段还没开始,$e ...

  3. php实现多图上传功能

    总共三个文化  index.html   conn.php  upload.php index.html代码: <html> <head>上传文件</head> & ...

  4. pywinauto进阶练习

    case1.画图工具简单练习 #_*_coding=utf-8_*_ import time from pprint import pprint import logging from logging ...

  5. C++基础 (7) 第七天 多态的原理 纯虚函数和抽象类 依赖倒置原则

    1 昨日回顾 2 多态的原理 1 要有继承 2 要有子类重写父类的虚函数 3 父类指针(或者引用)指向子类对象 (动态联编 虚函数表 3 证明vptr指针的存在 4 vptr指针在构造父类的时候是分步 ...

  6. css 垂直居中方法总结

    工作中遇到垂直居中问题,特此总结了一下几种方式与大家分享.本文讨论的垂直居中仅支持IE8+ 1.使用绝对定位垂直居中 HTML <div class="container"& ...

  7. [BZOJ1999] 树网的核 [数据加强版] (树的直径)

    传送门 如果只是想验证算法正确性这里是洛谷数据未加强版 Description 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边带有正整数的权,我们称T为树网(treenet ...

  8. 1、认识和安装MongoDB

    MongoDB简介:MongoDB是一个基于分布式文件存储的数据库,由C++语言编写.目的是为WEB应用提供扩展的高性能的数据存储解决方案.MongoDB是一个介于关系型数据库和非关系型数据库之间的产 ...

  9. js获取日期当天的开始时间和结束时间

    //函数调用传参格式为 2018-6-6或者2018.6.6//如:startUnix(2018-6-6) 返回的时间戳格式‘1528300799’ function startUnix($date) ...

  10. 【hiho一下 第八周】状态压缩·一

    [题目链接]:http://hihocoder.com/problemset/problem/1044 [题意] [题解] 设f[i][j]表示; 前i-1个位置已经决策完; 然后i-m+1..i这一 ...