当前位置: 首页 > news >正文

python开发 *进程数据隔离.守护进程,进程同步工具 * 180725

进程数据隔离.守护进程,进程同步工具


一.进程之间的数据隔离:
from multiprocessing import Process
n=100       #主程序中变量n=
def func():

    global n      #子进程中引用父进程中变量n,
    n=n-1
    return 111
if __name__=="__main__":  # "子进程必须写在它下面"
    n_l=[]                 # 创建一个新列表
    for i in range(100):    #计数
        p=Process(target=func)    #创建一个子进程,子进程对象是func
        p.start()       #向操作系统申请开启一个子进程  自动执行run 方法
        n_l.append(p)            # 将每一个子进程添加到列表中
    print(n_l)   #列表里是类似于<Process(Process-1, stopped)>的元素
    for p in n_l:  #循环遍历  每一个元素
        p.join()    #所有子进程都结束在执行下面的程序

    print(n)      #100     #结果=100 显然子进程并没有引用到父进程的变量.

 



进程之间的数据隔离:
总结:
1.进程与进程之间数据是隔离的,
2.内存空间是不能共享的
3.所以想要进行通信,必须借助其他手段,且这两个进程都是自愿的.
4.子进程的执行结果父进程获取不到
5.父进程如何获取子进程的执行结果:通过socket通信.

二.守护进程:
import time
from multiprocessing import Process
例一.
def func():
print("begin")
time.sleep(3)
print("wahaha")
if __name__=="__main__":
p=Process(target=func)
p.daemon=True
注意:
# 属性:守护进程的属性,默认是False,如果设置成True,就表示设置这个子进程为一个守护进程
# 守护进程的位置:设置守护进程的操作应该在开启子进程之前

p.start()
time.sleep(1)
print("主进程") #结果 只打印begin 主进程,
#例二:
def func1():
    print("begin")               #2打印begin
    time.sleep(3)                 #3 休三秒
    print("wahaha")              #12.打印 wahaha
def func2():
    while True:
        print("in func2")        #7.打印 in func2   9.打印infunc2
        time.sleep(0.5)           #8.睡0.5秒
if __name__=="__main__":
    Process(target=func1).start()   #1 创建一个子进程,子进程对象为func1,并向操作系统申请开启
    p=Process(target=func2)         #4 再创建一个子进程,子进程对象为func2,
    p.daemon=True                   #5.设置守护进程操作
    p.start()                       # 6.申请开启子进程func2
    time.sleep(1)                   #10睡 1秒
    print("主进程")                #11.打印主进程

  


总结:
守护进程会在主进程的代码执行完毕之后直接结束,无论守护进程是否执行完毕
应用:
报活 主进程还活着
为什么要用守护进程来报活,不用主进程来工作?
守护进程报活几乎不占用CPU,也不需要操作系统去调度
主进程不能严格的每60秒就发送一条信息.

三.进程同步的工具
相关知识:
进程 : 同一时刻可以做多件事情 互相之间不影响
进程之间是异步;
进程同步的工具:锁( Lock ),信号量( Semaphore ) ,事件( Event )
同步:有先后顺序
(一). 锁Lock
    from multiprocessing import Lock
    lock=Lock()    #创建一把锁
    #两个方法
    lock.acquire() #获取这把锁的钥匙
    lock.release() #归还这把锁的钥匙
#抢票的例子(每个人都能查看余票,买票

import json      #导入json模块
import time      #导入时间模块
from multiprocessing import Process  #导入Process模块
from multiprocessing import Lock      #导入Lock模块
def search(i):#定义一个查票函数
    with open("db","r")as f:                                    # 2 打开文件,读取文件数据
        count_dic=json.load(f)                                    # 3 将读取数据反序列化得到数据本身
        time.sleep(0.2)                                           # 4网络延迟  从数据库中读取内容需要消耗一定的时间.
        print("person%s 余票:%s张"%(i,count_dic["count"]))     # 5.显示用户信息和查询数据
def buy(i): #定义一个购票函数
    with open("db","r",encoding="utf-8")as f:         # 8.打开文件,读取数据
        count_dic=json.load(f)                          # 9.反序列化得到原数据
        if count_dic["count"]>0:                       # 10.判断剩余票数是否>0
            count_dic["count"]=count_dic["count"]-1   # 11.大于零则将原票数减1
            print("person%s购票成功"% i)              # 12显示用户购票成功
            time.sleep(0.2)                             # 13网络延迟  (给数据库传递新票务信息需要时间)
            with open("db","w",encoding="utf-8")as f: # 14打开文件
                json.dump(count_dic,f)                  # 15 将更改后的数据写进数据库

def task(i,lock): #定义一个任务函数
    search(i)                                           # 1 执行函数search ,将序号i传给函数search
    lock.acquire()                                      # 6.用lock的acquire方法获取这把锁钥匙    (buy函数被创建的锁锁住)
    buy(i)                                              # 7.执行函数buy()  并将参数i传给函数
    lock.release()                                      # 16 用户归还钥匙
if __name__=="__main__": #必须在这一步下面创建子进程
    lock=Lock()      #创建一个锁lock
    for i in range(10):   #计数10以下
        p=Process(target=task,args=(i,lock))  #创建一个子进程,子进程对象是task,有两个参数(一个是序号i,一个是加锁)  需要创建十个子进程
        p.start()     #申请开启一个子进程
应用:

 

 
 
    当多个进程共享一段数据的时候,数据会出现不安全的现象,需要加锁来维护数据的安全性
注意:
from multiprocessing import Lock
lock=Lock()
lock.acquire()
print(111)
lock.release()
lock.acquire()    # 阻塞状态  (只有一把钥匙已经被获取,且尚未归还)
print(222)    #不加只打印111
#解决办法: 只需要在第二次获取钥匙前将钥匙归还即加上  lock.release()    加上lock.release()就可以打印111,222

 


(二).信号量(Semaphore)
信号量的本质: 多把钥匙对应一把锁
lock+count计数
现象:
from multiprocessing import Process
from multiprocessing import Semaphore
sem=Semaphore(3)
sem.acquire()
print(1)
sem.acquire()
print(2)
sem.acquire()
print(3)
#sem.release()
sem.acquire()     #阻塞状态    如果加sem.release()
print(4)          #不打印
案例:商场唱吧(KTV)
场景:四个小房子,十个人排队等待进入房间
 import time    #导入时间模块
    import random   #导入random模块
    from multiprocessing import Process   #导入Process模块
    from multiprocessing import Semaphore  #导入Semaphore信号量 模块

    def ktv(num,sem):#定义一个函数ktv
        sem.acquire()                    # 1 获取一把钥匙     6 下一个用户(进程)获取钥匙
        print("person%s进入ktv"% num)  # 2 显示用户信息及正在使用状态
        time.sleep(random.randint(1,4))  # 3 使用时间段
        print("person%s离开ktv"% num)  # 4 显示用户离开
        sem.release()                    # 5 归还钥匙

    if __name__=="__main__":       #必须在这一条件下面创建新进程
        sem=Semaphore(4)             #可允许四人同时使用
        for i in range(10):         #计数  一共需要创建十个子进程
            p=Process(target=ktv,args=(i,sem)) # 创建一个子进程p 子进程对象为ktv.需要两个参数(序号,sem)
            p.start()                          # 申请开启一个子进程 归还钥匙后,

 


(三).事件(Event)
方法:
等待: wait() 如果这个标志是False 那么就阻塞
如果这个标志是True 那么就非阻塞
查看标志: is_set()
修改标志:set()将标志设置为True
clear()将标志设置为False
 现象:
from multiprocessing import Event
e = Event()
print(e.is_set())    #False    在事件创建之初默认是False
e.set()               #将标志设置为True
print(e.is_set())    #True
e.wait()             #相当于什么也没做
e.clear()            #将标志设置为False
e.wait(timeout=10)    #阻塞10秒如果信号在阻塞10s之内变为True,那么不继续阻塞直接pass,
#                     # 如果就阻塞10s之后状态还是没变,那么继续,
# e.wait()可以加参数  # 无论前面的wait的timeout是否通过,我的状态都不会因此改变
print(e.is_set())    #False

 

红绿灯模型:  控制交通灯的进程;
    import time
    import random
    from multiprocessing import Event
    from multiprocessing import Process

    def trafic_light(e):
        print("\033[1;31m红灯亮\033[0m")   # 1 打印红灯亮
        while True:                         #2无限循环
            time.sleep(2)                             #3睡两秒
            # print(1,e.is_set())   #f
            if e.is_set():                            # 4.条件e.is_set()=False:阻塞
                print("\033[1;31m红灯亮\033[0m")   #5.打印红灯亮
                e.clear()                            #6.修改is_set()的状态为False
                # time.sleep(3)
                # print(2,e.is_set())   #f
            else:                                    #7.e.si_set==True如果目前状态是True非阻塞
                print("\033[1;32m绿灯亮\033[0m")  #8.打印绿灯亮
                # print(4, e.is_set())    #f
                e.set()                              #9.设置is_set的状态为True 非阻塞(通行)
                # print(5,e.is_set())      #T

    def car(i,e):#车函数   (两种情况:等待,通行)
        # time.sleep(3)
        # print(3,e.is_set())     #True
        if not e.is_set():# 10.如果e.is_set()的状态是True 则not e.is_set()为False,现在状态是阻塞,
            print("car%sd等待"% i)   #11.  #先提示用户进入等待状态
            e.wait()                 #12.   #直接pass
        print("car%s通行"% i)     #13.和条件判断并行即条件不满足执行这一步
    if __name__=="__main__":
        e=Event()             #创建一个事件
        p=Process(target=trafic_light,args=(e,))   #创建一个进程对象为trafic_light ,参数为e
        p.start()     #申请开启进程
        for i in range(10):
            p=Process(target=car,args=(i,e))  #创建十个car进程,参数为i,e
            p.start()     #申请开启进程
            time.sleep(random.randrange(0, 3, 2))    #要么睡两秒,要么不睡.

 多进程解决tcp协议一个服务器与多个客户端通信矛盾

服务器端代码:

import socket
from multiprocessing import Process  #导入类Process
def talk(conn):      # 0 定义一个函数talk    6.执行talk进程
    try:
        while True:
            conn.send(b'alex')      #7.发送信息
            print(conn.recv(1024))   #8.接收信息
    finally:
        conn.close()

if __name__=="__main__":
    sk=socket.socket()           # 1 创建一个socket对象
    sk.bind(("127.0.0.1",9901)) # 2 绑定一个IP地址接口
    sk.listen()                  #3 监听
    try:
        while True:
            conn,addr=sk.accept()    #4 无限循环可支持多个客户端连接
            Process(target=talk,args=(conn,)).start() #5 连接以后需要开启一个正常收发信息进程.进程对象就是talk
               #并向操作系统提出执行talk进程的申请.
    finally:
        sk.close()

客户端代码:

import socket
import os
sk=socket.socket()
sk.connect(("127.0.0.1",9901))
while True:
    print(sk.recv(1024))
    sk.send(str(os.getpid()).encode('utf-8'))



sk.close()

 

转载于:https://www.cnblogs.com/J-7-H-2-F-7/p/9372385.html

相关文章:

  • 磁条卡,IC卡,ID卡,信用卡芯片卡,信用卡磁条卡 等等的区别
  • AI时代,APP运营是否会被淘汰
  • 初到湾区
  • android进程防杀套路【转】
  • 老K漫谈区块链的共识(1)——免信任的共识机制
  • 【Oracle】在win10上安装Oracle客户端报错:[INS-13001]环境不满足最低要求
  • Python、Linux与我的缘分
  • NSString 字符串
  • md5sum
  • jdbc就是这么简单
  • PhotoPickerDemo【PhotoPicker0.9.8的个性化修改以及使用(内部glide版本号是3.7.0)】...
  • php中类文件名的命名的规则是什么
  • Vue组件定义
  • SQL Server删除distribution数据库
  • 数据驱动的数字化转型:从流程驱动到数据驱动
  • 【391天】每日项目总结系列128(2018.03.03)
  • 0基础学习移动端适配
  • Android 控件背景颜色处理
  • Angular 响应式表单 基础例子
  • Electron入门介绍
  • emacs初体验
  • golang中接口赋值与方法集
  • JAVA SE 6 GC调优笔记
  • JavaScript异步流程控制的前世今生
  • Java基本数据类型之Number
  • mysql外键的使用
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • node 版本过低
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • Spring Boot MyBatis配置多种数据库
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • 对象引论
  • 服务器之间,相同帐号,实现免密钥登录
  • 学习使用ExpressJS 4.0中的新Router
  • 用Canvas画一棵二叉树
  • 《码出高效》学习笔记与书中错误记录
  • MyCAT水平分库
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (分布式缓存)Redis哨兵
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (六)c52学习之旅-独立按键
  • (一) storm的集群安装与配置
  • (一)python发送HTTP 请求的两种方式(get和post )
  • (转)es进行聚合操作时提示Fielddata is disabled on text fields by default
  • (转)http协议
  • (转)shell中括号的特殊用法 linux if多条件判断
  • (转)使用VMware vSphere标准交换机设置网络连接
  • (转)项目管理杂谈-我所期望的新人
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .NET Core WebAPI中使用Log4net 日志级别分类并记录到数据库
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .Net 高效开发之不可错过的实用工具
  • .NET 药厂业务系统 CPU爆高分析